Python中以指定字典为默认值的嵌套defaultdict出现字典实例共享问题
问题根源分析
嘿,这问题太典型了——你踩了Python可变对象引用的坑!
你定义的counter_format是一个可变字典对象,然后在嵌套defaultdict的lambda里直接返回它。这意味着所有新生成的嵌套字典,其实都指向同一个内存地址的counter_format对象。不管你修改哪个路径下的correct值,本质上都是在修改同一个字典,所以最后所有地方的数值都变成了3。
修复方案
解决思路很简单:每次需要默认值时,返回一个全新的字典实例,而不是复用同一个对象。这里有几种靠谱的实现方式:
方案1:直接在lambda里定义新字典
最直接的写法,省去单独的counter_format变量:
from collections import defaultdict userDict = defaultdict(lambda: defaultdict(lambda: {"correct": 0, "incorrect": 0}))
方案2:复用模板字典+浅拷贝
如果你想保留counter_format作为模板(比如后续要修改模板结构),可以用copy()方法每次生成新字典:
from collections import defaultdict counter_format = {"correct": 0, "incorrect": 0} userDict = defaultdict(lambda: defaultdict(lambda: counter_format.copy()))
注:这里用浅拷贝就足够,因为你的字典值都是不可变的整数。如果模板字典里还有嵌套可变对象,就得用
deepcopy了。
方案3:用数据类生成新实例(更优雅)
如果你的计数器结构后续可能扩展,用dataclasses会更清晰,每次生成新实例再转成字典:
from dataclasses import dataclass, asdict from collections import defaultdict @dataclass class Counter: correct: int = 0 incorrect: int = 0 userDict = defaultdict(lambda: defaultdict(lambda: asdict(Counter())))
验证效果
运行你原来的测试代码:
userDict['a'][1]['correct'] += 1 userDict['b'][1]['correct'] += 1 userDict['b'][2]['correct'] += 1
现在每个correct值都会独立更新,结果符合预期:
defaultdict(<function <lambda> at 0x10ca85ee0>, { 'a': defaultdict(<function <lambda>.<locals>.<lambda> at 0x10cbc0430>, {1: {'correct': 1, 'incorrect': 0}}), 'b': defaultdict(<function <lambda>.<locals>.<lambda> at 0x10cbc0b80>, { 1: {'correct': 1, 'incorrect': 0}, 2: {'correct': 1, 'incorrect': 0} }) })
内容的提问来源于stack exchange,提问作者jbogart
相关产品推荐
相关产品推荐

