为什么/当在Python中`x == y`调用`y .__ eq __(x)`? [英] Why/When in Python does `x==y` call `y.__eq__(x)`?
问题描述
Python文档清楚地表明 x == y
调用 x .__ eq __(y)
。然而,似乎在许多情况下,情况恰恰相反。在哪里或为什么会发生这种情况,它在哪里记录,我如何确定我的对象的 __ cmp __
或 __ eq __
方法将被调用。
The Python docs clearly state that x==y
calls x.__eq__(y)
. However it seems that under many circumstances, the opposite is true. Where is it documented when or why this happens, and how can I work out for sure whether my object's __cmp__
or __eq__
methods are going to get called.
编辑:为了澄清,我知道 __ eq __
在preferecne __ cmp __
,但我不清楚为什么 y .__ eq __(x)
优先于<$ c $
Just to clarify, I know that __eq__
is called in preferecne to __cmp__
, but I'm not clear why y.__eq__(x)
is called in preference to x.__eq__(y)
, when the latter is what the docs state will happen.
>>> class TestCmp(object):
... def __cmp__(self, other):
... print "__cmp__ got called"
... return 0
...
>>> class TestEq(object):
... def __eq__(self, other):
... print "__eq__ got called"
... return True
...
>>> tc = TestCmp()
>>> te = TestEq()
>>>
>>> 1 == tc
__cmp__ got called
True
>>> tc == 1
__cmp__ got called
True
>>>
>>> 1 == te
__eq__ got called
True
>>> te == 1
__eq__ got called
True
>>>
>>> class TestStrCmp(str):
... def __new__(cls, value):
... return str.__new__(cls, value)
...
... def __cmp__(self, other):
... print "__cmp__ got called"
... return 0
...
>>> class TestStrEq(str):
... def __new__(cls, value):
... return str.__new__(cls, value)
...
... def __eq__(self, other):
... print "__eq__ got called"
... return True
...
>>> tsc = TestStrCmp("a")
>>> tse = TestStrEq("a")
>>>
>>> "b" == tsc
False
>>> tsc == "b"
False
>>>
>>> "b" == tse
__eq__ got called
True
>>> tse == "b"
__eq__ got called
True
Mark Dickinson的回答和评论会出现:
From Mark Dickinson's answer and comment it would appear that:
- 丰富的比较覆盖
__ cmp __
-
__ eq __
是自己的__ rop __
到__ op__
(类似__ lt __
,__ ge __
等) - 如果左对象是内置或新式类,右边是它的子类,则在左对象的
__ rop __
code> __ op __
- Rich comparison overrides
__cmp__
__eq__
is it's own__rop__
to it's__op__
(and similar for__lt__
,__ge__
, etc)- If the left object is a builtin or new-style class, and the right is a subclass of it, the right object's
__rop__
is tried before the left object's__op__
这解释了 TestStrCmp
示例。 TestStrCmp
是 str
的子类,但不实现自己的 __ eq __
,因此在这两种情况下, str
的 __ eq __
优先(即 tsc ==由于规则1,b
调用 b .__ eq __(tsc)
为 __ rop __
)。
This explains the behaviour in theTestStrCmp
examples. TestStrCmp
is a subclass of str
but doesn't implement its own __eq__
so the __eq__
of str
takes precedence in both cases (ie tsc == "b"
calls b.__eq__(tsc)
as an __rop__
because of rule 1).
在 TestStrEq
示例中, tse .__ eq __
在两个实例中被调用,因为 TestStrEq
是 str
的子类,因此优先调用
In the TestStrEq
examples, tse.__eq__
is called in both instances because TestStrEq
is a subclass of str
and so it is called in preference.
在 TestEq
示例中, TestEq
implements __ eq __
和 int
不会因此 __ eq __
。
In the TestEq
examples, TestEq
implements __eq__
and int
doesn't so __eq__
gets called both times (rule 1).
但我还是不明白 TestCmp
的第一个例子。 tc
不是 int
上的子类,因此AFAICT 1 .__ cmp __(tc)$
But I still don't understand the very first example with TestCmp
. tc
is not a subclass on int
so AFAICT 1.__cmp__(tc)
should be called, but isn't.
推荐答案
你缺少一个常见行为的关键例外:当右手操作数是左手操作数的类的子类的实例时,右手操作数的特殊方法首先被调用。
You're missing a key exception to the usual behaviour: when the right-hand operand is an instance of a subclass of the class of the left-hand operand, the special method for the right-hand operand is called first.
请参阅以下文档:
http://docs.python.org/reference/datamodel.html#coercion-rules
,特别是以下两段: / p>
and in particular, the following two paragraphs:
对于
x
和y
,首先尝试
x .__ op __(y)
。如果这不是
实现或返回
未实现
,y .__ rop __(x)
试用。如果这也没有实现
或返回NotImplemented
,则会引发
TypeError异常。但是请参见
以下异常:
For objects
x
andy
, firstx.__op__(y)
is tried. If this is not implemented or returnsNotImplemented
,y.__rop__(x)
is tried. If this is also not implemented or returnsNotImplemented
, a TypeError exception is raised. But see the following exception:
对上一项的异常:如果
左操作数是
内置函数的实例, in类型或新式类
,右操作数是该类型或
类的适当子类的实例
,并覆盖基类的
__ rop __()
方法,右
操作数的 __ rop __()
方法在左操作数 __ op __()
方法。
Exception to the previous item: if the
left operand is an instance of a
built-in type or a new-style class,
and the right operand is an instance
of a proper subclass of that type or
class and overrides the base’s
__rop__()
method, the right
operand’s __rop__()
method is tried
before the left operand’s __op__()
method.
这篇关于为什么/当在Python中`x == y`调用`y .__ eq __(x)`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!