实现带默认值的嵌套字典类时重载[]运算符遇到的赋值失效问题
自定义默认值字典类嵌套修改失效的原因及解决办法
我来帮你分析这个问题,其实核心原因在于你实现的__getitem__方法的逻辑——当访问不存在的键时,你只是返回了默认值的深拷贝,但没有把这个拷贝存入字典的values中。
先看你的原始代码里的关键部分:
def __getitem__(self, key): return self.values[key] if key in self.values else deepcopy(self.default)
问题出在哪?
当你使用嵌套的Dict对象时:
- 第一次调用
d[KEY1],因为KEY1不在d.values里,所以返回一个deepcopy(Dict(42))的临时对象。 - 接着你修改这个临时对象的
KEY2:d[KEY1][KEY2] = 53——但这个修改只作用在那个临时对象上,并没有把这个临时对象存入d.values。 - 当你再次调用
d[KEY1]时,KEY1还是不在d.values里,所以又会生成一个全新的deepcopy(Dict(42)),自然看到的还是默认值42。
而普通类型(比如42)没问题,是因为当你执行d[KEY] = 53时,直接调用了__setitem__把值存入了values,后续访问就会取到这个设置的值,不会再触发默认值逻辑。
怎么解决?
只需要修改__getitem__方法,在返回默认值拷贝之前,先把它存入self.values,这样后续的操作就会作用在字典中存储的对象上:
from copy import deepcopy class Dict: def __init__(self, default) -> None: self.default = default self.values = {} def __getitem__(self, key): if key not in self.values: # 生成默认值拷贝并存入字典 self.values[key] = deepcopy(self.default) return self.values[key] def __setitem__(self, key, value): self.values[key] = value
现在再测试嵌套场景:
KEY1 = 'k1' KEY2 = 'k2' d = Dict(Dict(42)) print(d[KEY1][KEY2]) # 输出42 d[KEY1][KEY2] = 53 print(d[KEY1][KEY2]) # 现在输出53
这次就能得到预期结果了——因为第一次访问d[KEY1]时,生成的Dict(42)拷贝已经被存入d.values,后续修改d[KEY1][KEY2]就是直接修改这个存储在字典里的对象,下次访问自然能看到修改后的值。
内容的提问来源于stack exchange,提问作者user16004728
相关产品推荐
相关产品推荐

