В документах Python четко указано, что x==y вызывает x.__eq__(y). Однако кажется, что при многих обстоятельствах верно обратное. Где это описано, когда и почему это происходит, и как я могу точно определить, будут ли вызовы методы моего объекта __cmp__ или __eq__.
Изменить: просто чтобы уточнить, я знаю, что __eq__ вызывается в preferecne для __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__и т.д.) - Если левый объект является классом builtin или new-style, а правым является его подкласс, правый объект
__rop__проверяется перед левым объектом__op__
Это объясняет поведение в примерах TestStrCmp. TestStrCmp является подклассом str, но не реализует его собственный __eq__, поэтому __eq__ of 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) должен вызываться, но это не так.