Operator Overloading In Python with Easy Examples
In object-oriented programming, there exists this concept called “Polymorphism”. Polymorphism means “one action, many forms”. OOP allows objects to perform a single action in different ways. One way of implementing Polymorphism is through operator overloading. In this python tutorial, we are going to learn what is operator overloading in python with examples and also about magic methods in python.
Before we start with python operator overloading, let us revise python operators once.
What is Operator Overloading in Python?
Operator overloading is the process of using an operator in different ways depending on the operands. You can change the way an operator in Python works on different data-types.
A very popular and convenient example is the Addition (+) operator. Just think how the ‘+’ operator operates on two numbers and the same operator operates on two strings. It performs “Addition” on numbers whereas it performs “Concatenation” on strings.
Operators in Python work for built-in classes, like int, str, list, etc. But you can extend their operability such that they work on objects of user-defined classes too.
Let’s try it!
class bubble: def __init__(self, volume): self.volume = volume
We have defined a class bubble which has an attribute volume. Let’s see what happens when we combine two bubbles. We should get the volume of the combined bubble.
>>> b1 = bubble(20) >>> b2 = bubble(30)
And now let’s add b1 and b2 to merge the bubbles.
>>> b1 + b2
Clearly this doesn’t work right now. That’s because we haven’t extended its operability yet and it only works on built-in classes. So how do we make these operators work on our user-defined class bubble as well?
This is where “magic methods” come into the picture. Magic methods in Python are special methods that begin and end with a double underscore( __ ). The __init__() is one such method. Another magic method at our disposal is the __str__() method. The __str__() method lets you control how an object of your class gets printed. So if we add this method to our bubble class and print an object of the class, it should work as follows:
class bubble: def __init__(self, volume): self.volume = volume def __str__(self): return "volume is " + str(self.volume)
Now do this in the terminal:
>>> b1 = bubble(20) >>> print(b1)
Overloading ‘+’ operator
Lastly, let’s add the block of code which will make the ‘+’ operator operate on objects of bubble. Turns out, we have a magic method for this too, i.e, the __add__() method.
class bubble: def __init__(self, volume): self.volume = volume def __str__(self): return "volume is " + str(self.volume) def __add__(self, other): volume = self.volume + other.volume return bubble(volume)
In addition to ‘self’, the __add__() method takes another argument ‘other’. The ‘self’ and ‘other’ refer to the two objects acting as operands. We perform the addition of volumes of ‘self’ and ‘other’, and then assign this value to a new variable volume. The method then returns a new object of the class bubble with volume as its instance variable.
Let’s create a new object which is the sum of 2 bubbles:
>>> b1 = bubble(20) >>> b2 = bubble(30) >>> b3 = b1 + b2 >>> print(b3)
Now we can perform an addition on objects of our class. Let’s see what happens behind the scenes.
- When we add b1 + b2, the interpreter calls b1.__add__(b2).
- And b1.__add__(b2) is actually executed as bubble.__add__(b1, b2).
- This will then return bubble(50).
- So, b3 = b1 + b2 is actually equivalent to b3 = bubble(50).
In this way, we can overload other operators as well. Note that in the case of comparison operators, the magic method will return a boolean expression as a result of the comparison and not an object. You’ll find various python operators and their magic methods in the table below.
Magic methods in Python
|Addition||b1 + b2||__add__()|
|Subtraction||b1 – b2||__sub__()|
|Multiplication||b1 * b2||__mul__()|
|Division||b1 / b2||__truediv__()|
|Power||b1 ** b2||__pow__()|
|Floor division||b1 // b2||__floordiv__()|
|Modulo operator||b1 % b2||__mod__()|
|Bitwise left shift||b1 << b2||__lshift__()|
|Bitwise right shift||b1 >> b2||__rshift__()|
|Bitwise AND||b1 & b2||__and__()|
|Bitwise OR||b1 | b2||__or__()|
|Bitwise XOR||b1 ^ b2||__xor__()|
|Less than||b1 < b2||__lt__()|
|Less than equal to||b1 <= b2||__le__()|
|Greater than||b1 > b2||__gt__()|
|Greater than equal to||b1 >= b2||__ge__()|
|Equal to||b1 == b2||__eq__()|
|Not equal to||b1 != b2||__ne__()|
In this article, we learned to use a very special power that comes with polymorphism in Python. We learned what is operator overloading in Python. We also learned how we can extend the operability of an operator such that it can work on our user-defined classes.
If you like the article, feel free to share with your friends on social media.