Python Operator Overloading
FREE Online Courses: Your Passport to Excellence - Start Now
Modifying the behavior of an operator by redefining the method an operator invokes is called Operator Overloading. It allows operators to have extended behavior beyond their pre-defined behavior. Let us first discuss operators, operands, and their behavior before diving into the operator overloading.
Operators and Operands in Python
Special symbols in Python that we use to perform various operations on objects are called Operators. The objects on which operations are performed are called Operands. We say objects because everything is an object in Python.
Example of Operators in Python
num1 = 3 num2 = 4 addition = num1 + num2 print(addition)
Output
In the above code example, + is the operator that performs the addition operation on operands num1 and num2.
Behavior of Operators in Python
The behavior of operators, in Python, is different for different operands. The same operator performs different actions depending on the operands used. Let us understand this using the plus operator.
num1 = 20 num2 = 5 print(type(num1)) print(type(num2)) sum = num1 + num2 print(sum)
Output
<class ‘int’>
25
In the above code example, operands are two int objects and the plus operator returns their sum.
Operators on Strings in Python
str1 = "Python" str2 = "Geeks" print(type(str1)) print(type(str2)) str3 = str1 + str2 print(str3)
Output
<class ‘str’>
PythonGeeks
In the above code example, operands are two string objects and the plus operator returns their concatenated string.
Operators on Lists in Python
list1 = [1, 2, 3] list2 = [4, 5, 6] print(type(list1)) print(type(list2)) list3 = list1 + list2 print(list3)
Output
<class ‘list’>
[1, 2, 3, 4, 5, 6]
In the above code example, operands are two list objects and the plus operator joined the two lists and returned the joined list.
From the above three code examples, we can see that the plus operator performs three different operations depending on the operands. It performs the sum operation if the operands are numbers, concatenation if the operands are strings, and join operation if the operands are lists. Similarly, operators in Python have different behaviors for different operands.
Magic Methods in Python
Python contains a special type of method called Magic Methods or Special Methods or Dunder Methods. These methods have two underscores before and after their name. Usually, we never directly call those functions. Python invokes them internally.
For example, whenever we create an object, Python invokes __init__ method to instantiate the object and whenever we use an operator, Python internally calls the corresponding magic method.
class Fruit: def __init__(self): print("Object Created") obj1 = Fruit()
Output
We can see in the above code example, we never directly called the __init__ method. Python invoked it as soon as we defined an object.
Limitations of Operators in Python
Operators have certain limitations depending on their operands. For example, the + operator can not perform addition if the operands are objects other than numbers, strings, tuples, and lists. It runs a TypeError instead of a sum.
class Fruit: def __init__(self, num): self.num = num obj1 = Fruit(10) obj2 = Fruit(25) sum = obj1 + obj2 print(sum)
Output
In the above code example, when we try to add two Fruit objects, Python returns a TypeError.
We can remove these limitations through operator overloading and make the + operator return something instead of an error.
Operator Overloading in Python
Python gives us the ability to modify the operation of an operator when used for specific operands. Every time we use an operator, Python internally invokes a magic method. In the case of +, Python invokes the __add__ method.
We can redefine this method in our object’s class to create a custom operation for the + operator. This is also called Operator Ad-hoc Polymorphism.
class Fruit: def __init__(self, num): self.num = num def __add__(self, other): sum = self.num + other.num return f"{self.num} fruits + {other.num} fruits = "\ f"{sum} fruits" obj1 = Fruit(5) obj2 = Fruit(4) objs = obj1 + obj2 print(objs)
Output
In the above code example, we used the plus operator for two Fruit objects. Since we redefined the __add__ method, + returned a string instead of an error.
Similarly, operator overloading can be done for all types of operators except logical and identity operators in Python.
Types of Operators in Python
There are seven types of operators in Python. Among those, we can overload five types of operators.
Types of operators in Python we can overload
Arithmetic operators | Comparison operators | Assignment operators |
Bitwise operators | Membership operators |
Types of Python operators we can not overload
Logical operators | Identity operators |
Arithmetic Operators in Python
Arithmetic operators are two types: Unary operators and Binary Operators.
1. Unary Operators in Python
Operator | Method |
+ | __pos__ |
– | __neg__ |
~ | __invert__ |
Example: Negative Operator (-)
class Number: def __init__(self, num): self.num = num def __neg__(self): print("Negative Operator") return self.num n1 = Number(5) print(-n1)
Output
5
In the above code example, by overloading the ‘-’ operator, we made it always print a string and return a positive number instead of a negative number.
2. Binary Operators in Python
Operator | Method |
+ | __add__ |
– | __sub__ |
* | __mul__ |
/ | __truediv__ |
// | __floordiv__ |
% | __mod__ |
** | __pow__ |
Example: Modulus Operator (%)
class Number: def __init__(self, num): self.num = num def __mod__(self, other): return self.num / other.num n1 = Number(10) n2 = Number(2) print(n1 % n2)
Output
In the above code example, we overloaded the ‘%’ operator to return the quotient of the division instead of the remainder.
Comparison Operators in Python
Operator | Method |
> | __gt__ |
< | __lt__ |
== | __eq__ |
>= | __ge__ |
<= | __le__ |
!= | __ne__ |
Example: Equal-to Operator (==)
class Strings: def __init__(self, str): self.str = str def __eq__(self, other): if len(self.str) == len(other.str): return "Equal" else: return "Not Equal" word1 = Strings("Mom") word2 = Strings("Dad") print(word1 == word2)
Output
In the above code example, Instead of checking whether two strings are the same or not, we redefined the equal-to operator to check whether two strings are of equal length or not.
Assignment Operators in Python
Operator | Method |
+= | __iadd__ |
-= | __isub__ |
*= | __imul__ |
/= | __idiv__ |
//= | __ifloordiv__ |
%= | __imod__ |
**= | __ipow__ |
>>= | __irshift__ |
<<= | __ilshift__ |
&= | __iand__ |
^= | __ixor__ |
|= | __ior__ |
Example: Addition Assignment Operator (+=)
class Fruit: def __init__(self, num): self.num = num def __iadd__(self, other): new = self.num + 5 return Fruit(new) obj = Fruit(5) print(f"Before addition {obj.num = }") obj += 1 print(f"After addition {obj.num = } ")
Output
After addition obj.num = 10
In the above code example, we overloaded the ‘+=’ operator to always add 5 instead of the given number.
Bitwise Operators in Python
Operator | Method |
>> | __rshift__ |
<< | __lshift__ |
& | __and__ |
^ | __xor__ |
| | __or__ |
~ | __invert__ |
Example: And Operator (&)
class Number: def __and__(self, other): return "Overloaded '&' Operator" n1 = Number() n2 = Number() print(n1 & n2)
Output
In the above code example, we overloaded the ‘&’ operator to return a string.
Membership Operators in Python
Operator | Method |
in | __contains__ |
not in |
These operators are a bit different. Membership operators ‘in’ and ‘not in’ both invoke the same method __contains__.
Any value in the return statement is automatically converted into a boolean value, that is, either True or False.
Example: in and not in Operators
class Book: def __contains__(self, item): print("Book is empty") return False b1 = Book() b2 = Book() print(b2 in b1) print(b2 not in b1)
Output
False
Book is empty
True
In the above code example, we overloaded the __contains__ method. So the ‘in’ operator always returns False and the ‘not in’ operator always returns True.
Python Interview Questions on Operator Overloading
Q1. Overload the minus (-) operator to print the string “Subtracting”.
Ans 1. Complete code is as follows:
class Class1: def __sub__(self, other): return "Subtracting" print(Class1() - Class1()
Output
Q2. Inverse the role of the greater-than (>) operator by making it perform the less-than operation.
Ans 2. Code is as follows:
class Number: def __init__(self, num): self.num = num def __gt__(self, other): if self.num < other.num: return True else: return False a = Number(5) b = Number(10) print(a > b)
Output
Q3. Overload the + operator to easily add 2D coordinates.
Ans 3. Code is as follows:
class Coordinates: def __init__(self, x, y): self.x = x self.y = y def __add__(self, other): x1 = self.x + other.x y1 = self.y + other.y return (x1, y1) p1 = Coordinates(2, 5) p2 = Coordinates(5, 3) print(p1 + p2)
Output
Q4. Change the role of the multiply operator to the dividing operator.
Ans 4. Code is as follows:
class Numbers: def __init__(self, x): self.x = x def __mul__(self, other): return self.x / other.x num1 = Numbers(4) num2 = Numbers(2) print(num1 * num2)
Output
Q5. What is the output of the following code?
class Lists: def __init__(self, li): self.li = li def __add__(self, other): dic = {x:y for x,y in zip(self.li, other.li)} return dic li1 = Lists([1,2,3]) li2 = Lists(["one", "two", "three"]) print(li1 + li2)
Ans 5. The output of the given code is
{1: ‘one’, 2: ‘two’, 3: ‘three’}
Quiz on Python Operator Overloading
Conclusion
In this article, we learned about operators and how to overload them. Overloading operators come in handy in several situations. When we are working on geometry projects, overloading the addition operator to add coordinates is one of the many examples where we can use Python Overloading.
Furthermore, if you have any queries, please feel free to share them with us in the comment section.