Python怎么遍历字典的键、值和键值对

顾言
顾言
发布时间:2026-10-26| 7人浏览过
原创

在 Python 日常开发中,字典(dict)是存储结构化映射数据的核心容器。无论是解析来自后端接口的 JSON 响应、读取服务配置项,还是统计字频,遍历字典都是最高频的基础操作。掌握 Python 遍历字典的完整方法,关键在于按需选择三个维度的提取路径:直接或通过 keys() 遍历键、通过 values() 遍历值,以及通过 items() 同步解包键值对。

Python怎么遍历字典的键、值和键值对
图 1:Python 字典遍历的三种核心维度及其输入输出映射

一、遍历字典的键(Keys)

当你只需要读取字典中存在的所有属性名称,或者仅需要依据键做逻辑判断时,遍历键是最直接的操作。在 Python 中,遍历字典的键有两种书写方式:直接遍历字典对象与显式调用 .keys() 方法。

1. 直接遍历字典(推荐的标准写法)

在 Python 的迭代协议中,字典本身就是一个可迭代对象,其默认迭代器产出的就是字典的键。因此,最简洁、符合 Pythonic 风格的写法是直接对字典使用 for 循环:

# 准备演示字典
user_profile = {
    "id": 1024,
    "name": "Alice",
    "role": "Admin",
    "status": "Active"
}

# 方式一:直接遍历字典对象
for key in user_profile:
    print(key)

# 示例输出:
# id
# name
# role
# status

2. 显式调用 dict.keys()

你也可以使用字典的内置方法 user_profile.keys()。这种方式与直接遍历字典在运行效率与产出结果上完全一致:

# 方式二:显式调用 keys() 方法
for key in user_profile.keys():
    print(key)

选择依据:在普通的 for 循环中,直接写 for key in d: 更干净自然;而当你需要向阅读代码的人强调“此处仅处理键集合”,或者需要进行集合运算(如求两个字典键的交集 d1.keys() & d2.keys())时,使用 .keys() 会使语义更加清晰。

二、遍历字典的值(Values)

在很多业务场景下,我们并不关心字段名称,只关心字典中保存的实际数值。例如计算商品总价、统计用户得分总和、或者判断是否有任意一项状态不合规。这时应使用 .values() 方法。

实用场景:数值累加与数据清洗

# 学生期末成绩字典
student_scores = {
    "Math": 95,
    "English": 88,
    "Physics": 92,
    "Chemistry": 85
}

# 遍历所有科目的成绩并计算均分
total_score = 0
for score in student_scores.values():
    total_score += score

average_score = total_score / len(student_scores)
print(f"总分: {total_score}, 平均分: {average_score:.2f}")

# 示例输出:
# 总分: 360, 平均分: 90.00

因为 student_scores.values() 返回的是一个可迭代的视图对象,在不需要显式编写 for 循环体时,还可以直接将其传递给内置聚合函数,如 sum(student_scores.values()) 或 max(student_scores.values()),执行速度更快且代码极其精炼。

三、遍历字典的键值对(Items)与元组解包

当正文逻辑同时依赖字段名(键)和对应内容(值)时,切忌使用 for k in d: val = d[k] 这种先取键再按键寻址的反模式。频繁哈希查找会带来额外的计算开销。最标准、高效的解法是使用 .items() 方法结合元组解包。

Python怎么遍历字典的键、值和键值对
图 2:for key, value in d.items() 的底层迭代与元组解包分解步骤

完整代码示例:格式化打印与解包

server_config = {
    "host": "127.0.0.1",
    "port": 8080,
    "timeout": 30,
    "debug": True
}

# 推荐解包写法:同时获取 key 和 value
for key, value in server_config.items():
    print(f"配置项: {key:<10} => 当前值: {value}")

# 示例输出:
# 配置项: host       => 当前值: 127.0.0.1
# 配置项: port       => 当前值: 8080
# 配置项: timeout    => 当前值: 30
# 配置项: debug      => 当前值: True

如果在 for 后只写了一个接收变量,例如 for item in server_config.items():,那么 item 将是一个包含两个元素的元组 ('host', '127.0.0.1')。显式提供两个变量 k, v 能让代码阅读体验更佳。

四、三种遍历方式的特征与选型对比

在 Python 3 中,.keys()、.values() 和 .items() 返回的都不是普通的列表(list),而是视图对象(View Objects)(类型分别为 dict_keys、dict_values 和 dict_items)。

Python怎么遍历字典的键、值和键值对
图 3:三种字典遍历方式的语法、底层对象与典型适用场景横向对比

视图对象的两大关键特性:

  1. 零内存冗余(惰性开销):与 Python 2 中 .keys() 直接在内存中复制一份静态列表不同,Python 3 的视图对象不会分配容纳所有键/值的额外内存,因此即便遍历上千万条数据的巨型字典,内存占用也始终保持极低。
  2. 动态联动反映:视图对象直接绑定原字典底层哈希桶。如果字典在外部发生修改,尚未完成遍历的视图会实时反映这些变更。

五、避坑指南:遍历中修改字典的异常与三种安全模式

许多初学者在编写“删除某些过期键”或“按条件更新字段”时,往往习惯直接在循环体内部调用 del 或新增键:

# 错误示例:边遍历边删除键
scores = {"a": 60, "b": 45, "c": 80}
for k, v in scores.items():
    if v < 60:
        del scores[k]  # 触发致命错误!

# 运行时报错:
# RuntimeError: dictionary changed size during iteration

异常原因:Python 的字典迭代器在启动时会记录哈希表当前的条目容量计数器。在迭代过程中,如果执行新增或删除键的操作,哈希表的内存结构会发生改变或发生重哈希(Rehash),这会导致迭代器内部的偏移索引紊乱。为了防止发生未定义行为或死循环,Python 解释器会主动抛出 RuntimeError 阻断执行。

Python怎么遍历字典的键、值和键值对
图 4:字典原地增删引发的运行时异常机理与三套工业级安全规避方案

安全方案代码实操:

target_dict = {"a": 10, "b": 20, "c": 30, "d": 40}

# 方案 A 实操:使用 list() 快照进行原位修改
for k in list(target_dict.keys()):
    if target_dict[k] < 25:
        del target_dict[k]

print("方案 A 处理后:", target_dict)
# 示例输出:方案 A 处理后: {'c': 30, 'd': 40}

# 方案 B 实操:使用字典推导式直接过滤出新字典
raw_data = {"apple": 5, "banana": 0, "orange": 12}
filtered_data = {k: v for k, v in raw_data.items() if v > 0}

print("方案 B 过滤后:", filtered_data)
# 示例输出:方案 B 过滤后: {'apple': 5, 'orange': 12}

六、进阶技巧:排序遍历与索引编号

1. 按键或按值排序后遍历

字典本身维护的是插入顺序。如果需要按照字母表或数值大小有序输出,可以配合 sorted() 函数:

inventory = {"banana": 30, "apple": 50, "cherry": 20}

# 1. 按照键(水果名称字母顺序)排序遍历
for fruit in sorted(inventory):
    print(f"{fruit}: {inventory[fruit]}")

# 示例输出:
# apple: 50
# banana: 30
# cherry: 20

# 2. 按照值(库存数量由小到大)排序遍历
for fruit, count in sorted(inventory.items(), key=lambda item: item[1]):
    print(f"低库存预警: {fruit} -> {count}")

# 示例输出:
# 低库存预警: cherry -> 20
# 低库存预警: banana -> 30
# 低库存预警: apple -> 50

2. 在遍历时获取循环序号(enumerate)

如果业务中需要类似“序号 1、2、3”的自增行号,可直接对 .items() 包装 enumerate() 函数。注意在解包时,外层接收序号,内层元组再解包键值对:

languages = {"Python": 1991, "Java": 1995, "Rust": 2010}

# 采用 (key, value) 括号完成嵌套元组解包
for idx, (lang, year) in enumerate(languages.items(), start=1):
    print(f"[{idx}] {lang} 首发于 {year} 年")

# 示例输出:
# [1] Python 首发于 1991 年
# [2] Java 首发于 1995 年
# [3] Rust 首发于 2010 年

总结速查

遍历目标 推荐语法 底层返回值类型 核心关注点
只遍历键 for k in d: dict_keys 代码最简练,默认迭代器行为。
显式强调键 for k in d.keys(): dict_keys 可读性好,支持集合运算(并集、交集)。
只遍历值 for v in d.values(): dict_values 适用于数值累加、统计或直接传给聚合函数。
同时遍历键与值 for k, v in d.items(): dict_items 标准元组解包,性能最优,避免二次哈希查找。
遍历中删除键 for k in list(d.keys()): list 快照 避免 RuntimeError 字典大小变更错误。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。