Как обрабатывается __eq__ в Python и в каком порядке?

Так как Python не предоставляет левые/правые версии своих операторов сравнения, как он определяет, какую функцию вызывать?

class A(object):
    def __eq__(self, other):
        print "A __eq__ called"
        return self.value == other
class B(object):
    def __eq__(self, other):
        print "B __eq__ called"
        return self.value == other

>>> a = A()
>>> a.value = 3
>>> b = B()
>>> b.value = 4
>>> a == b
"A __eq__ called"
"B __eq__ called"
False

Это, как представляется, вызывает обе функции __eq__. Просто ищем официальное дерево решений.

Ответ 1

Выражение a == b вызывает A.__eq__, так как оно существует. Его код включает self.value == other. Поскольку int не знает, как сравнивать себя с B, Python пытается вызвать B.__eq__, чтобы узнать, знает ли он, как сравнивать себя с int.

Если вы измените свой код, чтобы показать, какие значения сравниваются:

class A(object):
    def __eq__(self, other):
        print "A __eq__ called: %r == %r ?" % (self, other)
        return self.value == other
class B(object):
    def __eq__(self, other):
        print "B __eq__ called: %r == %r ?" % (self, other)
        return self.value == other

a = A()
a.value = 3
b = B()
b.value = 4
a == b

он напечатает:

A __eq__ called: <__main__.A object at 0x013BA070> == <__main__.B object at 0x013BA090> ?
B __eq__ called: <__main__.B object at 0x013BA090> == 3 ?

Ответ 2

Когда Python2.x видит a == b, он пытается выполнить следующее.

  • Если type(b) является классом нового стиля, а type(b) является подклассом type(a), а type(b) имеет переопределенную __eq__, тогда результат b.__eq__(a).
  • Если type(a) имеет переопределенный __eq__ (то есть type(a).__eq__ isnt object.__eq__), тогда результат a.__eq__(b).
  • Если type(b) имеет переопределенный __eq__, то результат b.__eq__(a).
  • Если это не так, Python повторяет процесс, ищущий __cmp__. Если он существует, объекты равны, если он возвращает zero.
  • В качестве окончательного спада Python вызывает object.__eq__(a, b), который является True iff a и b - это один и тот же объект.

Если какой-либо из специальных методов возвращает NotImplemented, Python действует так, как будто метод не существует.

Обратите внимание, что последний шаг тщательно: если ни a, ни b не перегружают ==, то a == b совпадает с a is b.


От https://eev.ee/blog/2012/03/24/python-faq-equality/

Это поможет кому-то, надеюсь.