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

7

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’>
<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’>
<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’>
<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

Object Created

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

TypeError: unsupported operand type(s) for +: ‘Fruit’ and ‘Fruit’

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

5 fruits + 4 fruits = 9 fruits

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

Negative Operator
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

5.0

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

Equal

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

Before addition obj.num = 5
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

Overloaded ‘&’ Operator

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

Book is empty
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

Subtracting

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

True

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

(7, 8)

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

2.0

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.

Your 15 seconds will encourage us to work even harder
Please share your happy experience on Google | Facebook


Leave a Reply

Your email address will not be published. Required fields are marked *