Jonas Adler
Jonas Adler

Reputation: 10799

Equality and inheritance in python

When reading about how to implement __eq__ in python, such as in this SO question, you get recommendations like

class A(object):
    def __init__(self, a, b):
        self._a = a
        self._b = b

    def __eq__(self, other):
        return (self._a, self._b) == (other._a, other._b)

Now, I'm having problems when combining this with inheritance. Specifically, if I define a new class

class B(A):
    def new_method(self):
        return self._a + self._b

Then I get this issue

>>> a = A(1, 2)
>>> b = B(1, 2)
>>> a == b
True

But clearly, a and b are not the (exact) same!

What is the correct way to implement __eq__ with inheritance?

Upvotes: 3

Views: 3743

Answers (2)

ecatmur
ecatmur

Reputation: 157444

When performing a comparison between objects of two types where one type is derived from the other, Python ensures that the operator method is called on the derived class (in this case, B).

So to ensure that B objects compare dissimilarly to A objects, you can define __eq__ in B:

class B(A):
    def __eq__(self, other):
        return isinstance(other, B) and super(B, self).__eq__(other)

Upvotes: 4

Błotosmętek
Błotosmętek

Reputation: 12927

If you mean that instances of different (sub)classes should not be equal, consider comparing their types as well:

def __eq__(self, other):
    return (self._a, self._b, type(self)) == (other._a, other._b, type(other))

In this way A(1, 2) == B(1,2) returns False.

Upvotes: 6

Related Questions