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 →

Back to Blog

相关文章

阅读更多 »