在新式类中实现__getitem__

Pav*_*sko 5 python python-2.7

我有这个代码:

class A:
    def __init__(self):
        def method(self, item):
            print self, ": Getting item", item
        self.__getitem__ = types.MethodType(method, self, self.__class__)

class B(object):
    def __init__(self):
        def method(self, item):
            print self, ": Getting item", item
        self.__getitem__ = types.MethodType(method, self, self.__class__)
Run Code Online (Sandbox Code Playgroud)

然后这工作正常:

a = A()
a[0]
Run Code Online (Sandbox Code Playgroud)

但这不是:

b = B()
b[0]
Run Code Online (Sandbox Code Playgroud)

引发TypeError.

我发现新式类在类__dict__中寻找魔术方法而不是实例__dict__.这是正确的吗?为什么会这样?你知道任何解释背后的想法的文章吗?我试过RTFM,但也许不是正确的或没有抓到的东西......

非常感谢你!保罗

Mar*_*ers 6

这在Python数据模型文档中有记录:新样式类的特殊方法查找:

对于新式类,只有在对象的类型上定义,而不是在对象的实例字典中,才能保证对特殊方法的隐式调用才能正常工作.

这种行为背后的基本原理在于一些特殊的方法,如__hash__()__repr__()被所有对象,包括类型对象实现.如果这些方法的隐式查找使用了传统的查找过程,那么在类型对象本身上调用它们时会失败[.]

所以,因为两者hash(int) hash(1)必须工作,特殊的方法查找的类型,而不是实例上.如果__hash__()直接在对象上查找,hash(int)将被转换为int.__hash__(),那将失败,因为它int.__hash__()是一个未绑定的方法,它希望在(例如)的实际实例上调用; 因此,应该调用:int()1hash(int)type.__hash__()

>>> hash(1) == int.__hash__(1)
True
>>> hash(int) == type.__hash__(int)
True
>>> int.__hash__()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor '__hash__' of 'int' object needs an argument
Run Code Online (Sandbox Code Playgroud)

这是一个向后不兼容的更改,因此它仅适用于新式对象.