gpt4 book ai didi

python - 为什么/什么时候在 Python 中 `x==y` 调用 `y.__eq__(x)` ?

转载 作者:太空宇宙 更新时间:2023-11-03 12:08:13 27 4
gpt4 key购买 nike

Python 文档明确指出 x==y 调用 x.__eq__(y)。然而,在许多情况下,情况似乎恰恰相反。何时或为何发生这种情况的记录在哪里,以及我如何确定我的对象的 __cmp____eq__ 方法是否会被调用。

编辑:澄清一下,我知道 __eq____cmp__ 中被调用,但我不清楚为什么 y.__eq__(x) 优先于 x.__eq__(y) 调用,当后者是文档状态将发生的情况时。

>>> 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 的回答和评论看来:

  1. 丰富的比较覆盖 __cmp__
  2. __eq__ 是它自己的 __rop__ 到它的 __op__ (和 __lt__ 类似,__ge__等)
  3. 如果左边的对象是内置类或新式类,而右边是它的子类,则在左边对象的__op__之前尝试右边对象的__rop__

这解释了TestStrCmp 示例中的行为。 TestStrCmpstr 的子类,但没有实现自己的 __eq__ 所以 str 的 __eq__ 在这两种情况下都优先(即 tsc == "b" 调用 b.__eq__(tsc) 作为 __rop__ 因为规则 1).

TestStrEq 示例中,tse.__eq__ 在两个实例中都被调用,因为 TestStrEqstr 的子类> 所以它被优先调用。

TestEq 示例中,TestEq 实现了__eq__int 没有实现__eq__ 被调用两次(规则 1)。

但是我还是不明白第一个例子TestCmptc 不是 int 的子类,因此应该调用 AFAICT 1.__cmp__(tc),但实际上不是。

最佳答案

您遗漏了通常行为的一个关键异常:当右侧操作数是左侧操作数类的子类的实例时,首先调用右侧操作数的特殊方法。

请参阅文档:

http://docs.python.org/reference/datamodel.html#coercion-rules

特别是以下两段:

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:

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 - 为什么/什么时候在 Python 中 `x==y` 调用 `y.__eq__(x)` ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19400152/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com