I recently stumbled upon a seemingly strange behavior regarding the order in which __eq__
methods are executed, if one side of the comparison is an object which inherits from the other.
I've tried this in Python 3.7.2 in an admittedly academic example. Usually, given an equality comparison a == b
, I expect a.__eq__
to be called first, followed by b.__eq__
, if the first call returned NotImplemented
. However, this doesn't seem to be the case, if a
and b
are part of the same class hierarchy. Consider the following example:
class A(object):
def __eq__(self, other):
print("Calling A({}).__eq__".format(self))
return NotImplemented
class B(A):
def __eq__(self, other):
print("Calling B({}).__eq__".format(self))
return True
class C(object):
def __eq__(self, other):
print("Calling C({}).__eq__".format(self))
return False
a = A()
b = B()
c = C()
print("a: {}".format(a)) # output "a: <__main__.A object at 0x7f8fda95f860>"
print("b: {}".format(b)) # output "b: <__main__.B object at 0x7f8fda8bcfd0>"
print("c: {}".format(c)) # output "c: <__main__.C object at 0x7f8fda8bcef0>"
a == a # case 1
a == b # case 2.1
b == a # case 2.2
a == c # case 3.1
c == a # case 3.2
In case 1, I expect a.__eq__
to be called twice and this is also what I get:
Calling A(<__main__.A object at 0x7f8fda95f860>).__eq__
Calling A(<__main__.A object at 0x7f8fda95f860>).__eq__
However, in cases 2.1 and 2.2, b.__eq__
is always executed first, no matter on which side of the comparison it stands:
Calling B(<__main__.B object at 0x7f8fda8bcfd0>).__eq__ # case 2.1
Calling B(<__main__.B object at 0x7f8fda8bcfd0>).__eq__ # case 2.2
In cases 3.1 and 3.2 then, the left-hand side is again evaluated first, as I expected:
Calling A(<__main__.A object at 0x7f8fda95f860>).__eq__ # case 3.1
Calling C(<__main__.C object at 0x7f8fda8bcef0>).__eq__ # case 3.1
Calling C(<__main__.C object at 0x7f8fda8bcef0>).__eq__ # case 3.2
It seems that, if the compared objects are related to each other, __eq__
of the object of the child class is always evaluated first. Is there a deeper reasoning behind this behavior? If so, is this documented somewhere? PEP 207 doesn't mention this case, as far as I can see. Or am I maybe missing something obvious here?
Summary. Implement the Python __eq__ method to define the equality logic for comparing two objects using the equal operator ( == )
__class__ is an attribute on the object that refers to the class from which the object was created. a. __class__ # Output: <class 'int'> b. __class__ # Output: <class 'float'> After simple data types, let's now understand the type function and __class__ attribute with the help of a user-defined class, Human .
The __int__ method is called to implement the built-in int function. The __index__ method implements type conversion to an int when the object is used in a slice expression and the built-in hex , oct , and bin functions.
From the official documentation for __eq__
:
If the operands are of different types, and right operand’s type is a direct or indirect subclass of the left operand’s type, the reflected method of the right operand has priority, otherwise the left operand’s method has priority.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With