问题
In Python, everything has a class. Therefore dict
also has a class.
So, in theory, I should be able to change the implementation of the keyvalue assignment behavior.
Example:
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
I noticed that most objects have attributes listed in OBJECT.__dict__
or vars(OBJECT)
. But this isn’t the case for dict
or list
.
How can I get the desired behavior by overriding dict.__setattr__()
method?
回答1:
It is __setitem__
that have to be overriden in this case -
and it is as simples as:
class MyDict(dict):
def __setitem__(self, key, value):
dict.__setitem__(self, key, 2 * value)
Example:
>>> m = MyDict()
>>> m[0] = 5
>>> m
{0: 10}
__setattr__
controls how object attributes themselves (not key/value pairs) are attributed.
回答2:
Be careful when subclassing dict
. If you just override __setitem__
, then other dict
methods, such as update
, will not call your __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.
In order to create a dict-like object, you either need to subclass dict
and override all the methods (see OrderedDict for an example of this approach), or subclass collections.MutableMapping
and override a small subset those methods (from which all the other methods are derived).
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
回答3:
You can’t. The dict
class is written in C a Python builtin, which means you can’t really shouldn’t do any kind of monkey-patching on it.
You can, however, inherit from it and override whatever methods you want in your subclass.
回答4:
If you run the following code in the console you will see that the dict class/object is read-only:
{}.__setitem__ = None
AttributeError: 'dict' object attribute '__setitem__' is read-only
You need to what @jsbueno posted, which is create a subclass of the dict class, override the __setitem__
method, multiply the value by two and then call the original dict __setitem__
method.
来源:https://stackoverflow.com/questions/8752451/how-to-change-the-behavior-of-a-python-dictionarys-setattr