字典循环技巧
遍历字典是日常编程中最常见的操作之一。Python 提供了多种遍历方式,选择合适的方式能让代码更简洁、更高效。
遍历键
默认情况下,for 循环遍历字典的键:
d = {"a": 1, "b": 2, "c": 3}
for key in d:
print key
# 输出(顺序不确定):
# a
# c
# b
显式写法:
for key in d.iterkeys(): # 推荐,省内存
print key
for key in d.keys(): # 创建完整列表,不推荐
print key
遍历值
for value in d.itervalues():
print value
# 输出:
# 1
# 3
# 2
注意:遍历值时无法知道对应的键。如果需要键值一起处理,遍历键值对。
遍历键值对
for key, value in d.iteritems():
print key, "=", value
# 输出:
# a = 1
# c = 3
# b = 2
d.iteritems() 返回迭代器,每次产生一个 (key, value) 元组,然后拆包给 key 和 value。这是遍历字典最常用、最高效的方式。
对比低效写法:
# 低效:先查键,再查值
for key in d:
print key, d[key] # 两次哈希查找
# 高效:一次迭代直接获取键值对
for key, value in d.iteritems():
print key, value # 一次操作
同时修改字典的问题
在遍历字典时添加或删除键是危险的:
d = {"a": 1, "b": 2, "c": 3}
# 错误:遍历时删除
for key in d:
if key == "b":
del d[key] # RuntimeError: dictionary changed size during iteration
正确做法是遍历键的副本:
# 方法 1:遍历副本
for key in d.keys(): # keys() 返回列表(副本)
if key == "b":
del d[key]
# 方法 2:先收集要删除的键
keys_to_remove = [k for k in d if k == "b"]
for k in keys_to_remove:
del d[k]
# 方法 3:创建新字典(函数式风格)
d = {k: v for k, v in d.iteritems() if k != "b"}
按值排序
字典本身是无序的,但可以用 sorted() 按值排序:
scores = {"Alice": 85, "Bob": 92, "Charlie": 78}
# 按值升序
for name, score in sorted(scores.iteritems(), key=lambda x: x[1]):
print name, score
# 输出:
# Charlie 78
# Alice 85
# Bob 92
# 按值降序
for name, score in sorted(scores.iteritems(), key=lambda x: x[1], reverse=True):
print name, score
sorted() 接受一个可迭代对象,返回排序后的列表。key 参数指定排序依据,lambda x: x[1] 表示按元组的第二个元素(值)排序。
按键排序
d = {"banana": 3, "apple": 4, "pear": 1, "orange": 2}
# 按键字母顺序
for key in sorted(d):
print key, d[key]
# 输出:
# apple 4
# banana 3
# orange 2
# pear 1
合并两个字典
d1 = {"a": 1, "b": 2}
d2 = {"b": 20, "c": 3}
# 方法 1:update(修改 d1)
d1.update(d2)
print d1 # {'a': 1, 'c': 3, 'b': 20}
# 方法 2:创建新字典(不修改原字典)
merged = dict(d1, **d2)
# 或
merged = d1.copy()
merged.update(d2)
默认值模式
遍历字典时处理缺失键的常见模式:
# 模式 1:get() 提供默认值
for key in ["a", "b", "z"]:
value = d.get(key, 0)
print key, value
# 模式 2:setdefault() 初始化
for key in ["a", "b", "z"]:
d.setdefault(key, 0)
d[key] += 1
# 模式 3:collections.defaultdict(更优雅)
from collections import defaultdict
counts = defaultdict(int)
counts["a"] += 1 # 自动初始化为 0
反转字典
交换键和值:
d = {"a": 1, "b": 2, "c": 3}
# 简单反转(值必须唯一)
reversed_d = {v: k for k, v in d.iteritems()}
print reversed_d # {1: 'a', 2: 'b', 3: 'c'}
# 值不唯一时,分组
from collections import defaultdict
reversed_d = defaultdict(list)
for k, v in d.iteritems():
reversed_d[v].append(k)