Документы 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
Редактировать: Из ответа и комментария Марка Дикинсона может показаться, что:
- Богатое сравнение переопределений
__cmp__
__eq__
это собственный __rop__
к __op__
(и аналогичный для __lt__
, __ge__
и т. Д.)
- Если левый объект является встроенным классом или классом нового стиля, а правый является его подклассом, правый объект
__rop__
пробуется перед __op__
Это объясняет поведение в 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)
, но это не так.