Как __eq__ обрабатывается в Python и в каком порядке? - PullRequest
69 голосов
/ 28 августа 2010

Поскольку 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__ функции. Просто ищу официальное дерево решений.

Ответы [ 2 ]

87 голосов
/ 28 августа 2010

Выражение 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 ?
55 голосов
/ 20 октября 2012

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

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

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

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


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

...