Categories
Python

The Unique Elegant Way To Use Operator Overloading in Python

Each operator can be used in different way for different types of operands. for example when + is used with integers, it add integers to give result and when + is used with string, it concatenates the provided strings.

Have you ever wondered how operators work and if we can use them a little differently to suit our specific needs ?

Well if you haven’t, than it’s time you did. For this purpose, the concept of operator overloading exists in every language. Let’s see it in action and learn how to play with our objects with built-in operators.

Introduction To Operator Overloading

Surprising as it might be for some of us, each operator can be used in different way for different types of operands. For example, when + is used with integers, it add integers to give result. And when + is used with string, it concatenates the provided strings.

x, y = 10, 20
print(x + y) # 30
a,b = 'John', 'Wick'
print(a + b) # John Wick
This change in behavior of + operator according to type of operands provided, is typically known as Operator overloading. In other words, Operator overloading refers to the ability of operator to behave differently depending on operands it acts upon.  

The Basics Of Operator Overloading

To get familiar with Operator overloading, we first need to know the terms Python Data model and Special methods.

We can think of Python data model as an ‘Python Design’ or ‘Python Framework’. To clarify, it basically tells us how python manages objects and perform operations on them. Moreover, it exposes an API which you can use to make your objects work like built-in types. And use most of the idiomatic features of python language without implementing them. 

Special methods → When we use len(collection) method then python interpreter invokes collection’s __len__() method, right ? __len__() is a special method as well and just like it there exists many others.

Special method starts with __ and end with __ and are meant to be invoked by python interpreter only. Although, it can be invoked by us as well if we are doing metaprogramming. In other words, we need to use these special methods to achieve operator overloading.

Addition Of Two Objects Using + Operator

You must be wondering if + operator can even add two objects ? So let’s find it out together.

class Vector:

def __init__(self, x, y):
    self.x = x
    self.y = y
v1 = Vector(3, 4)
v2 = Vector(5, 6)
v1 + v2
TypeError                                 Traceback (most recent call last)
<ipython-input-3-08104d7e1232> in <module>
----> 1 v1 + v2

TypeError: unsupported operand type(s) for +: 'Vector' and 'Vector'

Executing the above piece of code will give you an error. Why? Because + operator does not know how to add two objects of Vector class. So now let’s make our Vector class support + operator using operator overloading in the process.

Whenever we call + operator, __add__(self, other) special method is invoked. And so to support + operator we just need to implement __add__() function in our class.

class Vector:

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Vector(self.x + other.x , self.y + other.y)

    def __repr__(self):
        return f'Vector({self.x}, {self.y})'

v1 = Vector(3, 4)
v2 = Vector(5, 6)

v1 + v2
# print 
# Vector(8, 10)

As evident from above code, now our Vector class holds a unique implementation of + operator. So now, when we try to add v1 and v2 objects of our Vector class. Then immediately the __add__() function gets invoked. And the addition operation is performed according to the logic specified in our __add__() function.

Similarly, we have implemented __repr__() method. So when we use print() function then the interpreter would invoke __str__() method.

Note: Always return new object when overloading operator unless you are overloading augmented assignment like += operator.

Equality Comparison Of Two Objects Using == Operator

Let us take one more example using == operator to get comfortable with operator overloading.

When we use == operator, the python interpreter invokes __eq__(self, other) special method. Likewise we can add our own implementation for __eq__() method and thus overload == operator.

class Vector:

    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Vector(self.x + other.x , self.y + other.y)

    def __repr__(self):
        return f'Vector({self.x}, {self.y})'
    
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y

v1 = Vector(3, 4)
v2 = Vector(5, 6)
v1 == v2 # False
v3 = Vector(3,4)
v1 == v3 # True

Limitations Of Operator Overloading

Operator Overloading in Python has some limitations as well, these are →

  • You cannot create new operators, only overloads existing ones.
  • You cannot overload operators for built-in types like tuple, string, list.
  • Few other operators also can’t be overloaded like is, or, and, not.

Conclusion

Operator overloading in python is easy to implement using special methods. The key in Python is to understand the Python data model and Special methods. These concepts enables us to get benefit of python idiomatic features and leverage powerful python standard library.

For future reference to understand python data model in more detail please refer Fluent python. Please find list of special methods in Python here.

Summary

Initially we had a brief introduction of Operator overloading. Then we had some digging around it’s concept which helps us achieve it. At the same time, we were introduced to the python data model and Special methods as well. Following that, we moved to the implementation part which was the core of our article. And at last we got to know the limitations imposed on operator overloading in Python.

I hope you have enjoyed this article.

Good Luck, Happy Coding

Let the author know what's in your mind !!

This site uses Akismet to reduce spam. Learn how your comment data is processed.