为什么我不能在collections.MutableMapping

时间:2017-10-05 23:00:53

标签: python

通常,我可以采用willy-nilly monkey-patch和mock方法:

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时在工作代码中发现了这一点。我将删除代码,或在将来使用子类,但我只是想了解发生了什么。

1 个答案:

答案 0 :(得分:2)

你可以在类上使用猴子补丁方法,但是new-style class实例上的猴子修补魔术方法没有奏效,因为新版本的类被引入了Python 2.2。新式类是object及其后代,并且出于多种原因(更好的性能,更少的奇怪边缘情况,支持superproperty setter等新功能,Python 3兼容性),你应该尽可能选择旧式的新式课程。

UserDict.DictMixin是一个旧式的课程。在实例上设置魔术方法仅适用于旧式类的实例。 collections.MutableMapping是一种新式的课程。

在Python 3中,没有旧式的类,所以如果在类型上设置,你将不得不习惯魔术方法。