Defining Equality#


Recall the Dog class we wrote in Lesson 13.

class Dog:
    def __init__(self, name):
        self._name = name

    def bark(self):
        print(f'{self._name}: Woof!')


d1 = Dog('Chester')
d2 = Dog('Chester')
d3 = d1

print(d1 is d2)
print(d1 is d3)
print(d1 == d2)

With our understanding of is , the first two examples should hopefully make sense. However, the third example ( d1 == d2 ) seems a bit surprising! It seems like these two Dog s should be considered value equal since they have the exact same state!

Unfortunately, Python does not automatically know how you want to define value-equality between Dog s. By default, Python will treat == on your object to mean the same thing as is , unless you tell it that value equality should be defined otherwise. In this reading, we will talk about how to tell Python what you want == to mean for your object.

To define what == should mean, you have to implement a special method called __eq__ . __eq__ will be called whenever you use == and its return value ( True or False ) determines the value of == . To be more concrete, x == y gets translated to x.__eq__(y) behind the scenes!

So let’s define the __eq__ method so that Dog s can be compared. Notice we are defining what equality means here for the Dog class. Let’s define it that two Dog s are equal if they have the same name (notice we could define it however we want, but with only one field, there aren’t a lot of options).

Note

Even though _name is a private field on the Dog class, it is okay for one Dog to access the private fields of another Dog . The rationale here is you are the one that wrote the Dog class, so you should know how to use their private fields without causing any errors.

class Dog:
    def __init__(self, name):
        """
        Creates a new Dog object with the given name
        """
        self._name = name

    def bark(self):
        """
        Prints a message for this dog barking.
        """
        # Uses a slightly fancier syntax called string interpolation
        # You don't need to be able to write these, but we wanted
        # to show off this feature. Everything inside {} gets
        # evaluated in Python!
        print(f'{self._name}: Woof!')

    def __eq__(self, other):
        """
        Returns true if other has the same name as this Dog
        """
        return self._name == other._name


d1 = Dog('Chester')
d2 = Dog('Chester')
d3 = d1

print(d1 is d2)
print(d1 is d3)
print(d1 == d2)

And now this code block prints what we would expect.