from UserDict import DictMixin
class py2fake_dict(DictMixin):
def __setitem__(self, name, value):
raise AssertionError("Don't talk to me!")
def __delitem__(self, name):
pass
def __getitem__(self, name):
pass
def __iter__(self):
yield None
def __len__(self):
return 0
c = py2fake_dict()
c.__setitem__ = lambda name, value: 'All clear.'
# This is OK:
c[1] = 2
但是,如果有问题的方法是在MutableMapping子类上,我不能:
from collections import MutableMapping
class py3fake_dict(MutableMapping):
def __setitem__(self, name, value):
raise AssertionError("Don't talk to me!")
def __delitem__(self, name):
pass
def __getitem__(self, name):
pass
def __iter__(self):
yield None
def __len__(self):
return 0
c = py3fake_dict()
c.__setitem__ = lambda name, value: 'All clear.'
# This hits the assertion!!!
c[1] = 2
作为Python3升级的一部分,我在从UserDict.DictMixin
升级到collections.MutableMapping
时在工作代码中发现了这一点。我将删除代码,或在将来使用子类,但我只是想了解发生了什么。
答案 0 :(得分:2)
你可以在类上使用猴子补丁方法,但是new-style class的实例上的猴子修补魔术方法没有奏效,因为新版本的类被引入了Python 2.2。新式类是object
及其后代,并且出于多种原因(更好的性能,更少的奇怪边缘情况,支持super
和property
setter等新功能,Python 3兼容性),你应该尽可能选择旧式的新式课程。
UserDict.DictMixin
是一个旧式的课程。在实例上设置魔术方法仅适用于旧式类的实例。 collections.MutableMapping
是一种新式的课程。
在Python 3中,没有旧式的类,所以如果在类型上设置,你将不得不习惯魔术方法。