Python怎么按条件过滤并遍历字典

青禾
青禾
发布时间:2026-11-13 | 5人浏览过
原创

详细讲解在Python中按键或值过滤并遍历字典的常见方法,分析直接循环、推导式与生成器的内存差异,并提供就地安全修改字典的避坑方案。

在 Python 中按条件过滤并遍历字典,核心是围绕字典的键值项视图(d.items())与条件判断展开。最直接的做法是在常规 for 循环中通过 if 语句筛选符合条件的数据;如果后续仍需多次使用过滤后的结果,可优先采用字典推导式构建新字典;若数据规模较大且仅需一次性流式处理,则推荐使用生成器表达式或直接迭代以节省内存开销。

一、过滤与遍历的决策路径

面对不同的业务场景与数据量级,选择合适的语法能让代码在可读性与运行性能之间取得平衡。主要考量点包括三方面:是否只需单次读取、是否需要保存过滤结果、以及是否涉及在遍历过程中修改原字典。

Python怎么按条件过滤并遍历字典

图 1:按条件过滤与遍历字典的整体决策逻辑

二、方法一:常规 for 循环配合 if 条件(推荐用于单次消费)

对于绝大多数常见的业务场景(例如打印、累加计数、写入日志或将合格项发送到外部接口),直接使用 for key, value in d.items(): 结合 if 是最自然、可读性最好的方式。

# 示例:遍历字典,筛选分数不低于 80 分的学生
scores = {
    "Alice": 85,
    "Bob": 58,
    "Charlie": 92,
    "Diana": 76,
    "Evan": 95
}

for name, score in scores.items():
    if score >= 80:
        print(f"优秀学员: {name}, 得分: {score}")

这种写法的特点在于:

  • 零额外内存分配:scores.items() 在 Python 3 中返回一个字典项视图(dict_items),不复制底层数据,直接遍历原字典项。
  • 短路控制灵活:如果业务需要满足某个条件时提前终止,可以直接在 if 内部使用 break,避免多余的遍历开销。

三、方法二:字典推导式(推荐用于后续复用)

如果过滤出来的键值对需要在多个地方被反复查询或传参,应当将其组织为一个全新的字典。此时使用字典推导式(Dictionary Comprehension)是最规范、惯用的 Python 表达方式。

scores = {
    "Alice": 85,
    "Bob": 58,
    "Charlie": 92,
    "Diana": 76,
    "Evan": 95
}

# 1. 使用推导式生成只包含及格学生的新字典
passed_scores = {name: score for name, score in scores.items() if score >= 60}

# 2. 遍历新字典
for name, score in passed_scores.items():
    print(f"及格学员: {name} -> {score}")

推导式不仅可以对值进行过滤,还可以对键进行判断,甚至在过滤的同时对键或值做格式转换:

# 示例:仅过滤以字母 'A' 或 'C' 开头的键,并将姓名转为大写
filtered_upper = {
    name.upper(): score 
    for name, score in scores.items() 
    if name.startswith(("A", "C"))
}

四、方法三:生成器表达式与 filter 函数(惰性流式处理)

当字典包含数十万甚至数百万条数据时,如果使用推导式生成一个全新的字典,会立即在内存中开辟一段空间用于存放过滤结果。若你只是想按顺序逐个消费这些数据,生成器表达式(Generator Expression)或内置的 filter() 能够以惰性求值的方式工作。

# 使用生成器表达式构建惰性迭代器
filtered_gen = ((k, v) for k, v in scores.items() if v >= 80)

# 逐项消费,不会一次性构建全量字典
for name, score in filtered_gen:
    print(f"流式读取: {name} = {score}")

同理,内置的 filter() 也可以达到类似效果:

# filter 接收一个过滤函数和迭代对象
filtered_iter = filter(lambda item: item[1] >= 80, scores.items())

for name, score in filtered_iter:
    print(f"filter 筛选: {name} = {score}")
Python怎么按条件过滤并遍历字典

图 2:不同过滤机制的数据流转与内存占用对比

五、重要陷阱:为什么不能边遍历边直接删除键?

很多初学者在需要“清除字典中所有不合格数据”时,会直觉性地写出如下代码:

# 错误示例:边遍历边删除
scores = {"Alice": 85, "Bob": 58, "Charlie": 92}
for name, score in scores.items():
    if score < 60:
        del scores[name]  # 运行时直接抛出异常!

运行该代码时,Python 解释器会立即抛出:
RuntimeError: dictionary changed size during iteration

底层原因分析:Python 字典底层基于哈希表实现。在迭代字典的过程中,解释器维护了一个内部变更计数器(mutation count)。如果在迭代过程中对字典进行了增加或删除操作,哈希表的槽位可能发生重排或计数发生改变,迭代器在下一次取值时检测到长度不匹配,为了防止产生不可预知的死循环或漏项,会主动抛出 RuntimeError。

Python怎么按条件过滤并遍历字典

图 3:运行时异常表现与基于快照的防御机制

安全修改的正确方案

针对这一问题,有两种标准解决方案:

  • 方案 A(快照遍历法):使用 list(scores.keys()) 将所有键提取为一个独立的静态列表。遍历该列表时删除原字典中的键,因为迭代的是独立列表而非字典视图本身,不会产生冲突。
  • 方案 B(重构保留法):直接用推导式生成只保留合格数据的新字典,并重新赋值给原变量。这种方法代码最精炼,也是实际开发中最推荐的策略。
# 方案 A 演示:基于 list 快照安全删除
scores = {"Alice": 85, "Bob": 58, "Charlie": 92}
for name in list(scores.keys()):
    if scores[name] < 60:
        del scores[name]

# 方案 B 演示:推导式重构
scores = {k: v for k, v in scores.items() if v >= 60}

六、典型应用场景与综合对比

在复杂的生产环境中,过滤条件往往不仅限于简单的数字对比。常见需求包括复合条件判断、嵌套字典结构提取等。

1. 多条件复合过滤

# 过滤年龄大于 20 且状态为 active 的用户
users = {
    "u101": {"age": 25, "active": True},
    "u102": {"age": 18, "active": True},
    "u103": {"age": 30, "active": False},
}

for uid, info in users.items():
    if info["age"] > 20 and info["active"]:
        print(f"匹配用户 ID: {uid}, 年龄: {info['age']}")

2. 嵌套字典中指定属性的提取与扁平化遍历

# 提取所有状态正常的员工邮箱
departments = {
    "dev": {"lead": "alice@corp.com", "active": True},
    "ops": {"lead": "bob@corp.com", "active": False},
    "qa":  {"lead": "carol@corp.com", "active": True}
}

active_leads = {dept: info["lead"] for dept, info in departments.items() if info["active"]}
for dept, email in active_leads.items():
    print(f"部门: {dept} -> 负责人邮箱: {email}")
Python怎么按条件过滤并遍历字典

图 4:四种常见方案的特性与适用场景全景对比

总结建议:在日常 Python 开发中,单次处理优选“for ... in d.items(): if ...”;需要持久化过滤结果优选“字典推导式”;海量数据或流水线处理使用生成器;若需要在遍历过程中删除或过滤字典项,务必通过 list(d.keys()) 快照隔离或推导式重建,切勿在迭代中直接就地删除。

相关专题:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表