在Python编程中,字典是非常常用的数据结构,很多时候我们会先处理字典中的部分元素,之后还需要对剩下的元素做进一步操作。如何高效遍历字典的剩余元素,避免不必要的性能损耗和逻辑错误,是很多开发者需要掌握的技巧。

基础场景说明
我们先定义一个测试用的字典,后续的所有示例都会基于这个字典展开:
# 定义测试字典
test_dict = {
"name": "张三",
"age": 25,
"city": "北京",
"job": "开发工程师",
"hobby": "编程"
}
假设我们先处理掉name和age这两个键对应的元素,之后需要遍历剩下的city、job、hobby三个元素,下面介绍几种可行的策略。
策略一:使用字典视图配合集合差集
Python3中字典的keys()、values()、items()方法返回的是视图对象,支持集合运算,我们可以先记录已经处理过的键,再通过差集得到剩余键再遍历。
# 记录已经处理过的键
processed_keys = {"name", "age"}
# 获取剩余键对应的元素
for key in test_dict.keys() - processed_keys:
print(f"剩余键:{key},对应值:{test_dict[key]}")
这种方法的优势是逻辑清晰,不需要修改原字典,也不会产生额外的字典拷贝开销,适合需要多次判断剩余元素的场景。
策略二:使用迭代器手动推进
字典的items()方法返回的视图对象可以转换为迭代器,我们可以先遍历处理部分元素,再继续遍历迭代器剩下的内容,避免重复遍历整个字典。
# 将字典items转换为迭代器
dict_iter = iter(test_dict.items())
# 先处理前两个元素
for _ in range(2):
key, value = next(dict_iter)
print(f"已处理:{key} -> {value}")
# 遍历剩余元素
print("开始处理剩余元素:")
for key, value in dict_iter:
print(f"剩余元素:{key} -> {value}")
这种方法适合按顺序处理字典元素的场景,不需要额外记录已处理的键,但是需要注意如果迭代器已经耗尽再调用next会抛出StopIteration异常。
策略三:遍历时动态删除已处理元素
如果允许修改原字典,我们可以在遍历的时候直接删除已经处理过的元素,之后遍历剩下的字典内容即可。注意这种方法需要遍历字典的拷贝,避免遍历过程中修改字典大小导致报错。
# 遍历字典的拷贝,避免修改原字典大小导致报错
for key in list(test_dict.keys()):
if key in ("name", "age"):
print(f"已处理:{key} -> {test_dict[key]}")
# 删除已处理的元素
del test_dict[key]
# 遍历剩余元素
print("剩余元素:")
for key, value in test_dict.items():
print(f"{key} -> {value}")
这种方法的缺点是会修改原字典,如果后续还需要用到原字典的完整内容就不适用,适合处理完元素后不需要保留原字典的场景。
不同策略的性能对比
我们通过简单的测试对比三种策略的性能,测试字典包含10000个元素,先处理前100个,再遍历剩余9900个:
import time
# 构造测试大字典
big_dict = {i: i*2 for i in range(10000)}
# 测试策略一性能
start = time.time()
processed = set(range(100))
for key in big_dict.keys() - processed:
_ = big_dict[key]
print(f"策略一耗时:{time.time() - start:.6f}秒")
# 测试策略二性能
start = time.time()
iter_obj = iter(big_dict.items())
for _ in range(100):
next(iter_obj)
for _ in iter_obj:
pass
print(f"策略二耗时:{time.time() - start:.6f}秒")
# 测试策略三性能
start = time.time()
tmp_dict = big_dict.copy()
for key in list(tmp_dict.keys()):
if key < 100:
del tmp_dict[key]
for _ in tmp_dict:
pass
print(f"策略三耗时:{time.time() - start:.6f}秒")
通常测试下来,策略一的性能最优,策略二次之,策略三因为需要拷贝字典和删除元素,性能相对较差。
注意事项
- 如果需要在遍历过程中修改原字典,一定要遍历字典的拷贝或者使用
list(dict.keys())转换,避免触发RuntimeError: dictionary changed size during iteration错误。 - 字典在Python3.7+中是插入有序的,如果需要按顺序处理剩余元素,上述策略都可以保持原有顺序,低版本Python中字典是无序的,剩余元素的遍历顺序不固定。
- 如果剩余元素的数量很少,直接使用
for key in test_dict: if key not in processed: ...的方式也可以,性能差异可以忽略。