Python 字典视图是实时的(可能会导致你的代码出错)
发布: (2026年1月11日 GMT+8 03:16)
3 min read
原文: Dev.to
Source: Dev.to
快速测验
d = {"a": 1, "b": 2}
keys = d.keys()
print(keys)
d["c"] = 3
print(keys)
如果你期待:
dict_keys(['a', 'b'])
dict_keys(['a', 'b'])
那就错了。实际输出是:
dict_keys(['a', 'b'])
dict_keys(['a', 'b', 'c']) # ← 自动更新!
字典视图
.keys()、.values() 和 .items() 并不返回副本。
它们返回 视图对象——对字典的实时窗口,字典变化时会自动更新。
person = {"name": "Alice", "age": 30}
k = person.keys()
print(k) # dict_keys(['name', 'age'])
person["city"] = "NYC" # 添加键
print(k) # dict_keys(['name', 'age', 'city'])
- 视图内存效率高,因为它们不复制数据。
- 但是,如果你没有预料到它们会保持同步,可能会导致 bug。
在迭代时修改
在遍历实时视图的同时修改字典会抛出错误:
config = {"debug": True, "verbose": False, "temp_flag": True}
# 删除所有值为 True 的标志
for key in config.keys():
if config[key] is True:
del config[key] # 💥 RuntimeError!
错误
RuntimeError: dictionary changed size during iteration
视图在迭代过程中发生变化,Python 通过抛出异常来保护你。
安全做法:遍历快照
在修改之前将视图转换为列表(或其他静态容器):
config = {"debug": True, "verbose": False, "temp_flag": True}
# 转换为列表——创建快照
for key in list(config.keys()):
if config[key] is True:
del config[key]
print(config) # {'verbose': False}
list(config.keys()) 捕获当时的键集合,使得对原字典的修改是安全的。
实时视图的强大用法
当你需要实时监控字典变化时,实时视图非常便利:
cache = {}
cache_keys = cache.keys()
# ... 在代码的其他地方 ...
cache["user_123"] = data
cache["user_456"] = more_data
# cache_keys 自动反映所有新增
print(f"Cached: {len(cache_keys)} items") # 始终是最新的
无需每次都重新调用 .keys();视图会与字典保持同步。
结论
字典视图对象是实时的、内存高效且功能强大的——但如果你把它们当作静态对象使用,也可能成为细微 bug 的来源。了解何时使用视图,何时使用快照(例如 list(dict.keys())),可以帮助你编写更安全、更可预测的代码。
改编自即将出版的图书 Zero to AI Engineer: Python Foundations。
原文摘自 Substack →