Как обрабатывается __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/
Это поможет кому-то, надеюсь.