【发布时间】:2011-01-17 21:10:40
【问题描述】:
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 的回答和评论看来:
- 丰富的比较覆盖
__cmp__ -
__eq__是它自己的__rop__还是__op__(__lt__、__ge__等类似) - 如果左侧对象是内置或新样式类,而右侧是它的子类,则在左侧对象的
__op__之前尝试右侧对象的__rop__
这解释了TestStrCmp 示例中的行为。 TestStrCmp 是 str 的子类,但没有实现它自己的 __eq__ 所以 __eq__ 的 str 在这两种情况下都优先(即 tsc == "b" 调用 b.__eq__(tsc) 作为 __rop__ 因为规则 1)。
在TestStrEq 示例中,tse.__eq__ 在两个实例中都被调用,因为TestStrEq 是str 的子类,因此它被优先调用。
在 TestEq 示例中,TestEq 实现了 __eq__ 和 int 没有,所以 __eq__ 被调用两次(规则 1)。
但我仍然不明白TestCmp 的第一个例子。 tc 不是 int 的子类,因此应该调用 AFAICT 1.__cmp__(tc),但不是。
【问题讨论】:
标签: python comparison operator-overloading