Python用dict.fromkeys创建嵌套字典计数时全键值异常原因解析
核心问题成因
dict.fromkeys()的默认值绑定逻辑是导致输出异常的根本原因。
- 执行
p = dict.fromkeys(range(7), {})时,方法不会为0-6的每个键生成独立的空字典,而是把同一个空字典的内存引用,赋值给所有这些键。 - 这意味着无论你通过
p[0]、p[1]或是其他任意键访问内层的嵌套字典,本质上都是在操作内存里同一个字典对象。 - 你代码里的内层循环总共执行3+4+7=14次,每次循环都会对这个共享字典的
t值做一次更新,最终所有键对应的嵌套字典的t值都会累计到14,和你观察到的输出完全吻合。
可以用一行代码快速验证这个共享特性:
p = dict.fromkeys(range(3), {}) print(p[0] is p[1]) # 输出True,证明两个键指向同一个字典实例
修正实现方案
只需要在初始化时为每个键生成独立的嵌套字典、避免共享引用,就能得到正确结果,以下是两种可直接运行的写法:
- 最小改动版(完全沿用你原本的判断逻辑)
把原来的dict.fromkeys初始化替换为字典推导式,给每个键单独创建独立的空字典:# 为每个阶段键初始化独立的空嵌套字典 p = {l: {} for l in range(7)} runs = (3, 4, 7) for r in runs: for l in range(r): if "t" in p[l]: p[l]["t"] += 1 else: p[l]["t"] = 1 - 简洁优化版
提前把每个阶段的t计数初始化为0,去掉冗余的分支判断:# 为每个阶段独立初始化t的初始值为0 p = {l: {"t": 0} for l in range(7)} runs = (3, 4, 7) for r in runs: # 每经过一个阶段,对应计数加1 for l in range(r): p[l]["t"] += 1
两种写法运行后,都会得到符合预期的输出:
{0: {'t': 3}, 1: {'t': 3}, 2: {'t': 3}, 3: {'t': 2}, 4: {'t': 1}, 5: {'t': 1}, 6: {'t': 1}}
通用避坑提示
dict.fromkeys()仅适合搭配不可变类型的默认值(比如数字、字符串、元组)使用——这类对象无法被原地修改,不会出现共享引用的问题。如果需要给字典的键绑定可变类型的默认值(比如空字典、空列表),一定要通过字典推导式遍历每个键单独创建实例,不要把可变对象直接传给fromkeys的默认值参数。
内容的提问来源于stack exchange,提问作者Frank
相关产品推荐
相关产品推荐

