我有这段代码:
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__)
然后这很好用:
a = A()
a[0]
但这不是:
b = B()
b[0]
引发TypeError。
我发现新式类在类__dict__中寻找魔术方法而不是实例__dict__。这是正确的吗?为什么会这样?你知道任何解释背后的想法的文章吗?我尝试过RTFM,但也许不是正确的,或者没有抓住这个东西......
非常感谢! 保罗
答案 0 :(得分:6)
这在Python数据模型文档中有记录:Special method lookup for new-style classes:
对于新式类,只保证在对象的类型上定义特殊方法的隐式调用才能正常工作,而不是在对象的实例字典中。
和
这种行为背后的基本原理在于许多特殊方法,例如
__hash__()
和__repr__()
,它们由所有对象实现,包括类型对象。如果这些方法的隐式查找使用了传统的查找过程,那么当在类型对象本身上调用它们时会失败[。]
因此,因为hash(int)
和 hash(1)
都必须工作,所以会在类型而不是实例上查找特殊方法。如果直接在对象上查找__hash__()
,则hash(int)
将被转换为int.__hash__()
,这将失败,因为int.__hash__()
是一个未绑定的方法,并且它希望被调用在int()
的实际实例上(例如1
);因此,对于hash(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
这是向后兼容的更改,因此它仅适用于新式对象。
答案 1 :(得分:0)
如果对象的类是新式类,则只能查找特殊方法,而不像旧式类。您正在实例上定义__getitem__
方法,这对新样式类没有影响。
答案 2 :(得分:0)
默认迭代器在新样式类中不使用__getitem__
。请参阅http://grokbase.com/t/python/tutor/085k143q1r/new-style-classes-getitem-and-iteration以获取示例。似乎__getitem__
的行为已随python 2.2和新类型的类型而改变