I have this code:
我有这个代码:
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__)
Then this works fine:
然后这工作正常:
a = A()a[0]
But this does not:
但这不是:
b = B()b[0]
raising TypeError.
I found that new-style classes look for magic methods in class __dict__ instead of instance __dict__ . Is this right? Why is it so? Do you know about any article explaining the ideas behind? I tried RTFM, but maybe not the right ones or did not catch the thing...
我发现新式类在类__dict__中寻找魔术方法而不是实例__dict__。这是正确的吗?为什么会这样?你知道任何解释背后的想法的文章吗?我试过RTFM,但也许不是正确的或没有抓到的东西......
Thank you very much!Paul
非常感谢!保罗
3 个解决方案
#1
6
This is documented in the Python datamodel documentation: Special method lookup for new-style classes:
这在Python数据模型文档中有记录:新样式类的特殊方法查找:
For new-style classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary.
对于新式类,只有在对象的类型上定义,而不是在对象的实例字典中,才能保证对特殊方法的隐式调用才能正常工作。
and
The rationale behind this behaviour lies with a number of special methods such as
__hash__()
and__repr__()
that are implemented by all objects, including type objects. If the implicit lookup of these methods used the conventional lookup process, they would fail when invoked on the type object itself[.]这种行为背后的基本原理在于许多特殊方法,例如__hash __()和__repr __(),它们由所有对象实现,包括类型对象。如果这些方法的隐式查找使用了传统的查找过程,那么在类型对象本身上调用它们时会失败[。]
So, because both hash(int)
and hash(1)
must work, special methods are looked up on the type instead of on the instance. If __hash__()
was looked up straight on the object, hash(int)
would be translated to int.__hash__()
, and that would fail, because int.__hash__()
is an unbound method and it expects to be called on an actual instance of int()
(e.g. 1
); so for hash(int)
, type.__hash__()
should called instead:
因此,因为hash(int)和hash(1)都必须工作,所以在类型而不是实例上查找特殊方法。如果在对象上直接查找__hash __(),则hash(int)将被转换为int .__ hash __(),这将失败,因为int .__ hash __()是一个未绑定的方法,它希望在实际上调用int()的实例(例如1);所以对于hash(int),应该调用类型.__ 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
This is a backwards-incompatible change, so it only applies to new-style objects.
这是一个向后不兼容的更改,因此它仅适用于新式对象。
#2
0
Special methods are only looked up against an object's class if its a new-style class, unlike old-style ones. You're defining the __getitem__
method on the instance, which has no effect with the new-style class.
如果对象的类是新式类,则只能查找特殊方法,而不像旧式类。您正在实例上定义__getitem__方法,这对新样式类没有影响。
#3
0
The default iterators do not use__getitem__
in new style classes. See http://grokbase.com/t/python/tutor/085k143q1r/new-style-classes-getitem-and-iteration for an example.It seems like the behaviour of __getitem__
has changed with python 2.2 and the new style of classes
默认迭代器不在新样式类中使用_getitem__。有关示例,请参阅http://grokbase.com/t/python/tutor/085k143q1r/new-style-classes-getitem-and-iteration。似乎__getitem__的行为已随python 2.2和新的类样式而改变
#1
6
This is documented in the Python datamodel documentation: Special method lookup for new-style classes:
这在Python数据模型文档中有记录:新样式类的特殊方法查找:
For new-style classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary.
对于新式类,只有在对象的类型上定义,而不是在对象的实例字典中,才能保证对特殊方法的隐式调用才能正常工作。
and
The rationale behind this behaviour lies with a number of special methods such as
__hash__()
and__repr__()
that are implemented by all objects, including type objects. If the implicit lookup of these methods used the conventional lookup process, they would fail when invoked on the type object itself[.]这种行为背后的基本原理在于许多特殊方法,例如__hash __()和__repr __(),它们由所有对象实现,包括类型对象。如果这些方法的隐式查找使用了传统的查找过程,那么在类型对象本身上调用它们时会失败[。]
So, because both hash(int)
and hash(1)
must work, special methods are looked up on the type instead of on the instance. If __hash__()
was looked up straight on the object, hash(int)
would be translated to int.__hash__()
, and that would fail, because int.__hash__()
is an unbound method and it expects to be called on an actual instance of int()
(e.g. 1
); so for hash(int)
, type.__hash__()
should called instead:
因此,因为hash(int)和hash(1)都必须工作,所以在类型而不是实例上查找特殊方法。如果在对象上直接查找__hash __(),则hash(int)将被转换为int .__ hash __(),这将失败,因为int .__ hash __()是一个未绑定的方法,它希望在实际上调用int()的实例(例如1);所以对于hash(int),应该调用类型.__ 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
This is a backwards-incompatible change, so it only applies to new-style objects.
这是一个向后不兼容的更改,因此它仅适用于新式对象。
#2
0
Special methods are only looked up against an object's class if its a new-style class, unlike old-style ones. You're defining the __getitem__
method on the instance, which has no effect with the new-style class.
如果对象的类是新式类,则只能查找特殊方法,而不像旧式类。您正在实例上定义__getitem__方法,这对新样式类没有影响。
#3
0
The default iterators do not use__getitem__
in new style classes. See http://grokbase.com/t/python/tutor/085k143q1r/new-style-classes-getitem-and-iteration for an example.It seems like the behaviour of __getitem__
has changed with python 2.2 and the new style of classes
默认迭代器不在新样式类中使用_getitem__。有关示例,请参阅http://grokbase.com/t/python/tutor/085k143q1r/new-style-classes-getitem-and-iteration。似乎__getitem__的行为已随python 2.2和新的类样式而改变