We have already seen that the '+' operatior is used to add to numbers.
x = 5 y = 7 z = x + y print("The added result is :",z)
That was quite easy.
Now, let us say, we have a class that has an integer value. And we want to create two objects and add them.
Let me make it a little simpler with the below example.
class MyClass: def __init__(self, x): self.x = x obj1 = MyClass(5) obj2 = MyClass(7) obj3 = obj1 + obj2 print("The added result",obj3)
So, in the above code, we have created a class named 'MyClass' that has an attribute named 'x'.
And we have defined a Constructor that initialises the attribute 'x'.
def __init__(self, x): self.x = x
Then we have created an object 'obj1' of the class 'MyClass'.
And initialised the value of 'x' with '5'(For object 'obj1').
Similarly, we have created a second object 'obj2'.
And initialised the value of 'x' with '7'(For object 'obj2').
Now, we tried to add two objects 'obj1' and 'obj2'. Just to add '5' and '7'.
But we end up with the below error.
This is because Python is confused that how can adding two objects add their values?
With this we come to the concept of Overloading the operators. i.e. We will make the '+' operator act the waty, we want it to act.
Let us modify the above example.
class MyClass: def __init__(self, x): self.x = x def __add__(self,obj): return self.x + obj.x obj1 = MyClass(5) obj2 = MyClass(7) obj3 = obj1 + obj2 print("The added result",obj3)
And all we have done is, defined a method called 'def __add__(self,obj):'.
def __add__(self,obj): return self.x + obj.x
This '__add__( )' method is already defined by Python.
And all we are doing is, redefining the '__add__( )' method. So that it works exactly the way we want it to work.
So, the 'def __add__(self,obj):' has two parameters, 'self' and 'obj'.
Now, the '__add__( )' method gets called when the below statement executes.
And what happens is, the value of the object, 'obj1' is assigned to 'self' and 'obj2' is assigned to 'obj'.
And right now, 'self' has the contents of 'obj1',
And 'obj' has the contents of 'obj2',
Now, since, the '__add__( )' method has the contents,
def __add__(self,obj): return self.x + obj.x
The 'return' statement,
Adds the value of 'self.x' i.e. '5' and 'obj.x' i.e. '7'.
And the added value is returned to 'obj3'.
So, the print statement,
Prints the value of 'x' from the object 'obj3'. And we get the below output.
But have you thought, when we are executing the statement,
How come the 'def __add__(self,obj):' gets called?
This is because, for every operator, be it a '+' or '-' or any other operator, Python uses a method for each. And each method begins with double underscore '__' and ends with double underscore '__' followed by the name.
So, for '+', Python has the 'def __add__(self,obj):' method already defined. And all we are doing is, redefining the 'def __add__(self,obj):' in our class.
class MyClass: def __init__(self, x): self.x = x def __add__(self,obj): return self.x + obj.x
So, when Python finds the '+' operator for the objects of the class 'MyClass'.
At first, it searches for the 'def __add__(self,obj):' in the class 'MyClass'. And when it finds it.
def __add__(self,obj): return self.x + obj.x
It executes the task.
Similarly, Python has other methods for other operators as well. Let us see them below:
Operator | Expression | Overloaded Method |
---|---|---|
Addition | p1 + p2 | def __add__(self,obj) |
Subtraction | p1 - p2 | def __sub__(self,obj) |
Division | p1 / p2 | def __truediv__(self,obj) |
Multiplication | p1 * p2 | def __mul__(self,obj) |
Floor Division | p1 // p2 | def __floordiv__(self,obj) |
Modulo | p1 % p2 | def __mod__(self,obj) |
Power | p1 ** p2 | def __pow__(self,obj) |
Right Shift | p1 >> p2 | def __rshift__(self,obj) |
Left Shift | p1 << p2 | def __lshift__(self,obj) |
AND | p1 & p2 | def __and__(self,obj) |
OR | p1 | p2 | def __or__(self,obj) |
XOR | p1 ^ p2 | def __xor__(self,obj) |
NOT | ~p1 | def __invert__(self,obj) |
Equal to | p1 == p2 | def __eq__(self,obj) |
Not equal to | p1 != p2 | def __ne__(self,obj)) |
Greater than | p1 > p2 | def __ne__(self,obj) |
Greater than or equal to | p1 >= p2 | def __ge__(self,obj) |
Less than | p1 < p2 | def __lt__(self,obj) |
Less than or equal to | p1 <= p2 | def __le__(self,obj) |
So, if you want to overload, any of the above operators and customise it your way. You can use the corresponding overloaded method for it.