How is __eq__ handled in Python and in what order?
Since Python does not provide left/right versions of its comparison operators, how does it decide which function to call?
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
This seems to call both __eq__
functions.
I am looking for the official decision tree.
Solution 1:
The a == b
expression invokes A.__eq__
, since it exists. Its code includes self.value == other
. Since int's don't know how to compare themselves to B's, Python tries invoking B.__eq__
to see if it knows how to compare itself to an int.
If you amend your code to show what values are being compared:
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
it will print:
A __eq__ called: <__main__.A object at 0x013BA070> == <__main__.B object at 0x013BA090> ?
B __eq__ called: <__main__.B object at 0x013BA090> == 3 ?
Solution 2:
When Python2.x sees a == b
, it tries the following.
- If
type(b)
is a new-style class, andtype(b)
is a subclass oftype(a)
, andtype(b)
has overridden__eq__
, then the result isb.__eq__(a)
. - If
type(a)
has overridden__eq__
(that is,type(a).__eq__
isn'tobject.__eq__
), then the result isa.__eq__(b)
. - If
type(b)
has overridden__eq__
, then the result isb.__eq__(a)
. - If none of the above are the case, Python repeats the process looking for
__cmp__
. If it exists, the objects are equal iff it returnszero
. - As a final fallback, Python calls
object.__eq__(a, b)
, which isTrue
iffa
andb
are the same object.
If any of the special methods return NotImplemented
, Python acts as though the method didn't exist.
Note that last step carefully: if neither a
nor b
overloads ==
, then a == b
is the same as a is b
.
From https://eev.ee/blog/2012/03/24/python-faq-equality/