Object-Oriented Programming has four basic features, Inheritance, Data Abstraction, Data Encapsulation, and Polymorphism. And out of these features, Polymorphism is the crucial one, and if a Programming language does not support Polymorphism, it does not even consider an Object-Oriented Programming language.
As an object-oriented programming language, Python supports Polymorphism, and this tutorial will teach you what polymorphism is in Python and how to implement it. By the end of this tutorial, you will have a solid understanding of
- What is Polymorphism in Python
- Method Overriding
- What is function overloading and,
- Operator Overloading
What is Polymorphism in Python? OOPS Concept
Polymorphism is a Greek word that means “having Multiple Forms”, and in Programming, Polymorphism has the same concept but here it says an object can take many forms. In Python, the Polymorphism concept allows a particular object to perform different tasks in different scenarios.
The most common example of Polymorphism is the + operator. The + operator performs the addition operation between two number objects, and the same + operator performs string concatenation or joining between two string objects. This behaviour of the + operator, where it can take a different form in different scenarios, is a classical example of Polymorphism.
Note: Polymorphism does not apply to every Python object.
Another Real World Example of Polymorphism is you. You can be an Employee in a company, Husband or wife of your spouse and a striker while playing football. This acquiring of different forms at different places is what Polymorphism.
Let’s Build a solid understanding of Polymorphism with a common Python Example
Example: Python Polymorphism with len() function
In Python, you have used the len() function many times, as the name suggests, the len() function is generally used to calculate the total length of an object. But which length to compute depends upon the data type passed as an argument to the len() function.
For a list object, the len() function counts the total number of items present in the list. For a string, the len() function counts the total number of characters present in the string. For a dictionary object, the len() function counts the number of keys present in the dictionary.
The len() function name is the same for all the objects list, string, and dictionary, but it performs different operations on different objects. That is because Python supports Polymorphism.
Example
#list
employee = ['Rohan', 'Jay', 'Aman', 'Ravi', 'Shiv']
#string
message = 'welcome back to office'
#dictionary
jobs = {'Sales':3, 'IT':5, 'Management':2, 'Executive':1}
#count the list items
print("List count: ", len(employee))
#count the string characters
print('String Chracters count: ', len(message))
#count the dictionary keys
print('Dictionary Key Counts: ', len(jobs))
Output
List count: 5
String Chracters count: 22
Dictionary Key Counts: 4
How does Python Polymorphism work with Inheritance (Method Overriding)?
Mainly when it comes to class and objects we often use Polymorphism with Python inheritance . In Inheritance, the child or derived class can inherit the properties such as attributes, methods, and other data members from its parent or base class.
In method overriding, we first redefine a method in the child class with the same method name as the parent class. In method overriding, the inheriting of parent class methods in the child class is the concept of inheritance, and redefining the method with the same name is the concept of Polymorphism. This is how method overriding is a combination of two powerful object-oriented features.
Benefits of Method overriding
- Sometimes in inheritance, the parent class method does not satisfy the child class's functionality. We can extend the functionality by redefining the same method in the child class using method overriding.
- In multiple inheritances many child classes inherit from the single parent class, in that case, we can have method overriding in the child classes because there are solid chances that the parent class method does not fulfill all the requirements of all the child classes.
Example
Let’s write a Python program that demonstrates method overriding.
class Automobile():
def __init__(self, name, price, speed, gear):
self.name = name
self.price = price
self.speed = speed
self.gears = gear
def details(self):
print("Vehicle Name:", self.name)
print("Vehicle Price:", self.price)
print("Vehicle max Speed:", self.speed)
print("Vehicle total gears:", self.gears)
def speed_detail(self):
print("The Max Speed of the vehical is 120 Km/h")
def gears_detail(self):
print("This Vehicle has 5 gears")
#inherit the automobile class
class Car(Automobile):
#speed method overriding
def speed_detail(self):
print(f"The Max Speed of this car is {self.speed} Km/h")
#gears method overriding
def gears_detail(self):
print(f"This car has {self.gears} gears including reverse")
#inherit the automobile class
class Bike(Automobile):
#speed method overriding
def speed_detail(self):
print(f"The Max Speed of this Bike is {self.speed} Km/h")
#gears method overriding
def gears_detail(self):
print(f"This Bike has {self.gears} gears")
#Create the Car object
bmw = Car('BMW 3 Series', '44.86 Lakhs' ,'250', 'Automatic 8 Gear Box' )
bmw.details() #call the parent details method
bmw.speed_detail() #call the overriden method
bmw.gears_detail() #call the overriden method
print("\n\n")
#Create the Bike object
ktm = Bike('KTM 1190 RC8 R', '20 Lakhs', '280', '6' )
ktm.details() #call the parent details method
ktm.speed_detail() #call the overriden method
ktm.gears_detail() #call the overriden method
Output
Vehicle Name: BMW 3 Series
Vehicle Price: 44.86 Lakhs
Vehicle max Speed: 250
Vehicle total gears: Automatic 8 Gear Box
The Max Speed of this car is 250 Km/h
This car has Automatic 8 Gear Box gears including reverse
Vehicle Name: KTM 1190 RC8 R
Vehicle Price: 20 Lakhs
Vehicle max Speed: 280
Vehicle total gears: 6
The Max Speed of this Bike is 280 Km/h
This Bike has 6 gears
Built-in method overriding in Python
The code for built-in methods like abs(), len(), sum(), etc has already been written in the core Python <class object>. And by default, every class inherits the core Python object. We can see it by applying the mro() method to any class name. To override these inbuilt methods we can redefine their dunder methods for any custom class.
Example
class Orders:
def __init__(self):
self.cart = {'in process':[], 'canceled':[]}
def buy(self, item):
self.cart['in process'].append(item)
#override the len() function for Orders() objects
def __len__(self):
return len(self.cart['in process'])
my_orders = Orders()
my_orders.buy('Shoes')
my_orders.buy('Jackets')
#len function on my_orders object
in_process= len(my_orders)
print("Total Items in process", in_process)
Output
Total Items in process 2
In the above example, we override the inbuilt len() function for the Orders() class and every time we call the len() function on any of the Orders() object it will invoke the overridden method.
How Python Polymorphism in Class Methods works
When we create an object of Python and call a method on that object, Python links that objects with the method during the runtime. Python checks look for the method using Method Resolution Order, which is a technique used by Python objects to call the correct method or other attributes defined in the class. Let’s say we have two different classes, and they both have methods with the same names. When we create the objects for both the classes and call those methods, Python will link the correct object with the correct method.
Example
class Car():
def max_speed(self):
print("The Max Speed of Car is 350 KM/H")
class Bike():
def max_speed(self):
print("The Max Speed of Bike is 300 KM/H")
#create an object of Car
car = Car()
#create an object of bike
bike = Bike()
#call the max_speed of class Car
car.max_speed()
#call the max_speed of class Bike
bike.max_speed()
Output
The Max Speed of Car is 350 KM/H
The Max Speed of Bike is 300 KM/H
Car and Bike both have the same method names max_speed() in the above example. But the Car’s object car invoked the max_speed() method of Car , and the Bike’s object bike called the max_speed() of the Bike class.
What is Function Overloading in Python?
Function overloading is also one example of Polymorphism. In Function overloading, we have different functions of the same names, with different parameters. But unfortunately, Python does not support Function Overloading, this is because Python is an interpreted programming language, it read and executes the code simultaneously.
If we try to define a new function with the same name and different parameters, it will override the existing function instead of overloading. The function overloading is supported by Static programming languages like C++, C, and Java.
Example of Function overloading
def area(shape, radius):
result = 2 *3.14 *radius*radius
print("The Area of the given {shape} is: ", result)
#this will override the above area function not overload
def area(shape, length, width):
result = length * width
print(f"The Area of the given {shape} is: ", result)
#this will throw an error if executed
#area('circle',10)
area('rectangle, 10, 20)
Output
The Area of the given rectangle is: 200
Method overloading in Python is also not supported . The reason for not supporting method overloading is the same as function overloading.
What Operator Overloading in Python?
The operator overloading is an example of OOP’s Polymorphism, in which we can change the default behavior of an operator. The most common example of operator overloading is the Concatenation and Addition operator + . The + operator performs addition when both the values are integer or float, and it performs the string concatenation operation if both the values are of str data type.
Example
print(200+300) # 500 (addition)
print('200'+'300') #200300 (concatenation)
The above example demonstrates the inbuilt operator overloading of the + operator. But with Python operator overloading , we can change the default behavior of the operator for the class objects. To Overload the operators for class, we use the operator Magic Method, also known as the dunder method. Here is the list of all the operators and their dunder methods.
Operator | Dunder Methods |
+ | __add__(self, other) |
- | __sub__(self, other) |
* | __mul __ (self, other) |
/ | __div__(self, other) |
// | __floordiv__(self,other) |
% | __mod__(self, other) |
** | __pow__(self, other) |
+= | __iadd__(self, other) |
-= | __isub__(self, other) |
*= | __imul__(self, other) |
/+ | __idiv__(self, other) |
%= | __imod__(self, other) |
**= | __ipow__(self, other) |
< | __lt__(self, other) |
> | __gt__(self, other) |
<= | __le__(self, other) |
>= | __ge__(self, other) |
== | __eq__(self, other) |
!= | __ne__(self, other) |
Example 1: Overload the + operator for custom class object
Most operators require two operands to operate, so does the + operator. To overload the + operator for our custom class, we need to define the
__add__()
method in the Class. The __add__() method represent the + operator operation .
Example
class Products:
def __init__(self, items):
self.items = items
#here self is the object on the left side of + operator
# and other is the object on the right side of the + operator
def __add__(self, other):
return self.items + other.items
home = Products(200)
office = Products(400)
print("The total Products are:", home + office)
Output
The total Products are: 600
Note : The abovehome + office
statement is equivalent tohome.__add__(office)
.
Example 2: Overload the > operator for custom class object
Similar to the addition overloading, we can overload the greater than > operator with __gt__() method.
class Products:
def __init__(self, items):
self.items = items
#here self is the object on the left side of + operator
# and other is the object on the right side of the + operator
def __gt__(self, other):
return self.items > other.items
home = Products(200)
office = Products(400)
print("home > office = ", home > office)
Output
home > office = False
Conclusion
Polymorphism in Python allows performing method overriding and operator overloading, and it is one of the important properties of Object-Oriented Programming. With Polymorphism, an operator can have multiple behaviors with various data types or overload the operator's default behavior.
In this tutorial, we discussed Polymorphism in Python with the help of some examples. If you like this article or have any questions, please share your comments in the comment section down below.
People are also reading:
- Convert Seconds to hours, minutes and seconds in Python
- Python Programs to Print Pattern
- Python random sample() function to choose multiple unique items from any sequence
- Basic Python Exercise
- Declare a List in Python
- Python Instance Method
- Python Instance Variables
- Timestamp in Python
- Linked List in Python
- Python Object-Oriented Programming Exercise
Leave a Comment on this Post