Get startedGet started for free

Operator overloading: comparison

1. Operator overloading: comparison

Fantastic work on inheritance! By now, you've learned enough about classes and objects to start effectively using them in your applications. In this chapter, you'll learn how to make your objects seamlessly integrate with standard Python operations.

2. Object equality

Have you tried to compare two custom objects? Here are two objects of the Customer class that have the same data. If we ask Python if these objects are equal, the answer is "no". In this situation, it might make sense: we can have two customers with the same name and account balance.

3. Object equality

But what if each customer has a unique ID number? Then two customers with the same ID should be treated as equal.. but they aren't The reason why Python doesn't consider two objects with the same data equal by default has to do with how the objects and variables representing them are stored.

4. Variables are references

If we try to just print the value of a customer object, we'll see "Customer at" and a string (which is actually a number in hexadecimal). Behind the scenes, when an object is created, Python allocates a chunk of memory to that object, and the variable that the object is assigned to actually contains just the reference to the memory chunk. In this code, we tell Python: allocate a chunk of memory for a customer object, and label it customer1. Then, allocate another chunk, and label it customer2. When we compare variables customer1 and customer2, we are actually comparing references, not the data. Because customer1 and customer2 point to different chunks in memory, they are not considered equal.

5. Custom comparison

But it doesn't have to be that way! You might have noticed that, for example, numpy arrays are compared using their data. Here, we initialize two numpy arrays with the same data, and Python considers them equal. Same with pandas DataFrames, and many other objects. So how can we enforce this for our custom classes?

6. Overloading __eq__()

We can define a special method for this. Remember the __init__ constructor that is implicitly called when an object is created? The underscore-underscore-eq-underscore-underscore method is implicitly called whenever two objects of the the same class are compared to each other. We can re-define this method to execute custom comparison code. The method should accept two arguments, referring to the objects to be compared. They are usually called self and other by convention. It should always return a Boolean value -- True or False. Here, we have a basic Customer class with id and name attributes, and we redefine the eq method to return True if the values of all the attributes are equal. We also added a diagnostic printout for illustration.

7. Comparison of objects

Now, if we create two objects containing the same data and try to compare them using double equality sign, we see from the diagnostic printout that the eq method is called, and the comparison returns "True". On the other hand, if we create two objects with different id values, the comparison will return "False"

8. Other comparison operators

Python allows you to implement all the comparison operators in your custom class using special methods like eq. When you use a "not equal" operator -- that is, exclamation point followed by the equality sign -- Python will automatically attempt to use the equality method, if it exists, and then negate the result, but if you'd like to have a custom "not equals" method, you could implement __ne__. You could also implement, for example, "ge" for greater than or equal operator, or "lt" for less than. Finally, there is a hash method that allows you to use your objects as dictionary keys and in sets. It is beyond the scope of this course, but briefly, it should assign an integer to an object, such that equal objects have equal hashes, and the object hash does not change through the object's lifetime.

9. Let's practice!

Now, let's practice defining custom equality functions!