在Python中,一切都有一个类。因此dict
也有一个类。
因此,理论上,我应该能够改变keyvalue赋值行为的实现。
示例:
d = dict()
d['first'] = 3 # Internally d['first'] is stored as 6 [i.e. value*2 if value is INT]
print d['first'] # should print 6
d['second'] = 4
print d['second'] # should print 8
我注意到大多数对象都有OBJECT.__dict__
或vars(OBJECT)
中列出的属性。但dict
或list
并非如此。
如何通过覆盖dict.__setattr__()
方法获得所需的行为?
答案 0 :(得分:11)
在这种情况下必须覆盖__setitem__
-
它就像:
class MyDict(dict):
def __setitem__(self, key, value):
dict.__setitem__(self, key, 2 * value)
示例:
>>> m = MyDict()
>>> m[0] = 5
>>> m
{0: 10}
__setattr__
控制对象属性本身(不是键/值对)的归属方式。
答案 1 :(得分:8)
子类化dict
时要小心。如果您只是覆盖__setitem__
,则其他dict
方法(例如update
)将不会调用您的__setitem__
。
class MyDict(dict):
def __setitem__(self, key, value):
dict.__setitem__(self, key, 2 * value)
d = MyDict()
d['first'] = 3
print(d['first'])
# 6
d.update({'first':4})
print(d['first'])
# 4 # <--- __setitem__ was not called.
为了创建类似dict的对象,您需要子类dict
并覆盖所有方法(请参阅OrderedDict以获取此方法的示例)或子类collections.MutableMapping
并覆盖那些方法的小子集(从中派生所有其他方法)。
import collections
class MyDict2(collections.MutableMapping,dict):
def __getitem__(self, key):
return dict.__getitem__(self, key)
def __setitem__(self, key, value):
dict.__setitem__(self, key, 2 * value)
def __delitem__(self, key):
dict.__delitem__(self, key)
def __iter__(self):
return dict.__iter__(self)
def __len__(self):
return dict.__len__(self)
def __contains__(self, x):
return dict.__contains__(self, x)
d = MyDict2()
d['first'] = 3
print(d['first'])
# 6
d.update({'first':4})
print(d['first'])
# 8
答案 2 :(得分:2)
你做不到。 dict
类是用C 编写的一个Python内置函数,这意味着你不能真的不应该对它进行任何类型的猴子修补。
但是,您可以从中继承并覆盖子类中所需的任何方法。
答案 3 :(得分:1)
如果在控制台中运行以下代码,您将看到dict类/对象是只读的:
{}.__setitem__ = None
AttributeError: 'dict' object attribute '__setitem__' is read-only
你需要@jsbueno发布的内容,即创建dict类的子类,覆盖__setitem__
方法,将值乘以2,然后调用原始的dict __setitem__
方法。