I'm taking my first computing science course, and we just learned about class implementation and inheritance. In particular, we just covered method overriding and how classes we define inherit from the object
superclass by default. As one of my examples trying out this particular case of inheritance, I used the following code:
class A:
def __init__(self, i):
self.i = i
def __str__(self):
return "A"
# Commenting out these two lines to not override __eq__(), just use the
# default from our superclass, object
#def __eq__(self, other):
#return self.i == other.i
x = A(2)
y = A(2)
>>>print(x == y)
False
>>>print(x.__eq__(y))
NotImplemented
I expected the result from (x == y)
, because as I understand it the default for __eq__()
is to check if they're the same objects or not, not worrying about the contents. Which is False
, x
and y
have the same contents but are different objects. The second one surprised me though.
So my questions: I thought (x==y)
and x.__eq__(y)
were synonymous and made exactly the same call. Why do these produce differing output? And why does the second conditional return NotImplemented
?
The ==
operator is equivalent to the eq
function, which will internally call the __eq__
method of the left operand if it exists to try to determine equality. This is not the only thing it will do, and if __eq__
does not exist, as is the case here, it will do other checks, such as checking whether the two are the same object, or __cmp__
pre-Python 3.
So in a nutshell, your confusion arises from this assumption, which is incorrect:
I thought (x==y) and x.__eq__(y) were synonymous and made exactly the same call
In fact, (x==y)
and operators.eq(x, y)
are synonymous, and x.__eq__(y)
is one of the things eq(x, y)
will try to check.
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