我想在python3中编写一个dict子类,它包含一些dict方法并返回同一类的实例而不是__getitem__
上的dict,如果请求的值恰好是一个dict。否则,我想要的行为与dict的行为完全相同。这就是我想出的:
class WrappedDict(dict):
def __init__(self, stuff, *args, **kwargs):
super(WrappedDict, self).__init__(*args, **kwargs)
self.stuff = stuff
def update_stuff(self):
pass # Do things with stuff
def update(self, *args, **kwargs):
self.update_stuff(*args, **kwargs)
super(WrappedDict, self).update(*args, **kwargs)
def __getitem__(self, item):
obj = super(WrappedDict, self).__getitem__(item)
if isinstance(obj, dict):
return WrappedDict(self.stuff + str(item), obj)
else:
return obj
然而,这与dict不同,因为它不返回对dict值的引用,而是从该dict创建的新对象。说明我的意思:
d1 = {'a': 1, 'b': 2, 'c': {'d': 4}}
d1.update(a=10)
d2 = d1['c']
d2.update(d=40)
print(d1)
会给:
{'a': 10, 'b': 2, 'c': {'d': 40}}
但对WrappedDict
执行相同的操作:
wd1 = WrappedDict("stuff", {'a': 1, 'b': 2, 'c': {'d': 4}})
wd1.update(a=10)
wd2 = wd1['c']
wd2.update(d=40)
print(wd1)
给出:
{'a': 10, 'b': 2, 'c': {'d': 4}}
内部字典中的注释4而不是预期的40.有没有办法在没有太多黑魔法的情况下复制以前的行为?
答案 0 :(得分:1)
使用WrappedDict
__setitem__
设置回您的对象
def __getitem__(self, item):
obj = super(WrappedDict, self).__getitem__(item)
if isinstance(obj, dict):
wrapped = WrappedDict(self.stuff + str(item), obj)
super(WrappedDict, self).__setitem__(item, wrapped)
return wrapped
else:
return obj
完整代码:
class WrappedDict(dict):
def __init__(self, stuff, *args, **kwargs):
super(WrappedDict, self).__init__(*args, **kwargs)
self.stuff = stuff
def update_stuff(self, *args, **kwargs):
pass # Do things with stuff
def update(self, *args, **kwargs):
self.update_stuff(*args, **kwargs)
super(WrappedDict, self).update(*args, **kwargs)
def __getitem__(self, item):
obj = super(WrappedDict, self).__getitem__(item)
if isinstance(obj, dict):
wrapped = WrappedDict(self.stuff + str(item), obj)
super(WrappedDict, self).__setitem__(item, wrapped)
return wrapped
else:
return obj
d1 = {'a': 1, 'b': 2, 'c': {'d': 4}}
d1.update(a=10)
d2 = d1['c']
d2.update(d=40)
print(d1)
wd1 = WrappedDict("stuff", {'a': 1, 'b': 2, 'c': {'d': 4}})
wd1.update(a=10)
wd2 = wd1['c']
wd2.update(d=40)
print(wd1)
输出:
{'a': 10, 'b': 2, 'c': {'d': 40}}
{'a': 10, 'b': 2, 'c': {'d': 40}}