You need to enable JavaScript to run this app. Python用dict.fromkeys创建嵌套字典计数时全键值异常原因解析
优惠活动
大模型
产品
解决方案
定价
更多

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,证明两个键指向同一个字典实例

修正实现方案

只需要在初始化时为每个键生成独立的嵌套字典、避免共享引用,就能得到正确结果,以下是两种可直接运行的写法:

  1. 最小改动版(完全沿用你原本的判断逻辑)
    把原来的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
    
  2. 简洁优化版
    提前把每个阶段的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.11 22:45:03