为什么/当在Python中`x == y`调用`y .__ eq __(x)`? [英] Why/When in Python does `x==y` call `y.__eq__(x)`?

查看:216
本文介绍了为什么/当在Python中`x == y`调用`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:


  1. 丰富的比较覆盖 __ cmp __

  2. __ eq __ 是自己的 __ rop __ __ op__ (类似 __ lt __ __ ge __ 等)

  3. 如果左对象是内置或新式类,右边是它的子类,则在左对象的 __ rop __ code> __ op __

  1. Rich comparison overrides __cmp__
  2. __eq__ is it's own __rop__ to it's __op__ (and similar for __lt__, __ge__, etc)
  3. 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 and y, first x.__op__(y) is tried. If this is not implemented or returns NotImplemented, y.__rop__(x) is tried. If this is also not implemented or returns NotImplemented, 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆