Prashant Sharma — December 19, 2021
Beginner Programming Python

This article was published as a part of the Data Science Blogathon

Introduction

Assume there is a class called animal, but within that class, there are numerous forms such as dog, cat, and cow. That is, a common class animal consists of a variety of forms that come in a variety of shapes and sizes and perform a variety of functions. This entire phenomenon is defined by a single term: polymorphism. Polymorphism is a term used in Python to refer to an object’s ability to take on multiple forms. The term is derived from two distinct terms: poly, which means numerous, and morphs, which means forms.

Class and Objects

A class is a template for creating an object. In the following example, we create a class named-A and declare a variable x, which is then passed a value. The object x is created and the value of x is printed.
A simple example demonstrating the concept of class and object in Python:-
class A:
x = 5
object = A()
print(object.x)
Output:
5

Constructor

A constructor is a sort of subroutine in object-oriented programming. When an object is created within a class, the function constructor is used to assign values to data members. Almost every time we create an object in Python, we use the __init__() function. We use the __init__() function almost everywhere in polymorphism.

What is polymorphism in Python?

Polymorphism is a term used in Python to refer to a generic function name that may be used for several kinds. This notion is commonly used in Python’s object-oriented programming. As is the case with other programming languages like as Java and C++, polymorphism is implemented in Python for a variety of purposes, most notably Duck Typing, Operator and Method overloading, and Method overriding. This polymorphism may be accomplished in two distinct ways: overloading and overriding.

 

A straightforward demonstration of polymorphism in Python:-

>>>4+5
9
>>>"4"+"5"
45
>>>"ab"+"cd"
abcd
We can see from the above example that the addition operator is utilized in a variety of ways. In the first example, since the data given is two integer values, the operator performed a two-number addition.
And in the second example, the identical values are supplied as string data and the same operator concatenates the two strings (concatenation is the act of joining two strings end-to-end). In the third example, the data is two strings, but the operator is identical to the previous one, and it concatenates the two strings.
>>>"3"+"ab"
3ab
Although the first value is an integer, the addition operator concatenated the two texts in this case.
Thus, these were some of the most fundamental instances of polymorphism in Python.

How to use polymorphism?

Overloading

Overloading may be classified into two categories.
  • Operator Overloading
  • Method Overloading

Operator overloading

Operator overloading is a kind of overloading in which an operator may be used in ways other than
those stated in its predefined definition.
>>>print(2*7)
14
>>>print("a"*3)
aaa
Thus, in the first example, the multiplication operator multiplied two numbers; but, in the second, since
multiplication of a string and an integer is not feasible, the character is displayed three times twice.
Thus, it demonstrates how a single operator may be used in a variety of ways.
Overloading operators in practice
Example 1:
class Vehicle:
    def __init__(self, fare):
        self.fare = fare
bus= Vehicle(20)
car= Vehicle(30)
total_fare=bus+ car
print(total_fare)
Output:
Traceback (most recent call last):
File “G:рythоn рyсhаrm рrоjeсtmаin.рy”, line 7, in
    total_fare=bus+ car
TypeError: unsupported operand type(s) for +: ‘Vehicle’ and ‘Vehicle’
In the above example, an error occurred because Python is unable to combine two objects. In
this case, the item is a vehicle.
Now comes the time for operator overloading to be used.
Now we are going to overload the specific method __add__ operator.
class Vehicle:
def __init__(self, fare):
self.fare = fare
def __add__(self, other)://using the special function __add__ operator
return self.fare+ other.fare
bus= Vehicle(20)
car= Vehicle(30)
total_fare=bus+ car
print(total_fare)
Output:
50
By overloading the special function, we declare that whenever we use the plus operator in the object
total_fare=bus+car, their fares will be added.
Example 2: In this example, let us compare the fares of several modes of transport.
class Vehicle:
    def __init__(self, fare):
        self.fare = fare
    def __lt__(self, other):// relational operator  __lt__ is used here as the special function
        return self.fare< other.fare

bus= Vehicle(10)
car= Vehicle(30)
compare=bus< car
print(compare)
Output:
True
In the above example, the relational operator __lt__ is utilized as a special function to enable the operator
overloading.

Method Overloading

Overloading a method refers to a class that has many methods with the same name but perhaps distinct
parameters. While Python does not natively enable method overloading, there are numerous
techniques to do this. While method overloading is possible, only the most recently specified methods
are usable.
Let’s try to understand with the help of an example.
Assume a class A, within the class we have taken a function show which has a constructor self and
arguments with the default value None and None. Then I created an object and executed the function
with the object obj.show, but I didn’t supply any arguments, despite the fact that it would display None
and None since we set default values in the function area.
Example:
class A:
def show(self, a=None, b=None):
print(a,b)
obj=A()
obj.show()
Output:
None None
To supply another value, I must now use another method obj.show() with an argument.
Example:
class A:
def show(self, a=None, b=None):
print(a,b)
obj=A()
obj.show()
obj.show(4)
Output:
None None
4 None
The None value supplied to an in the function portion is substituted with 4 in the output. Part 4 is given
as an argument to the function call.
Now, let’s examine what happens if we send two arguments to the function call in the following example.
Example:
class A:
def show(self, a=None, b=None):
print(a,b)
obj=A()
obj.show()
obj.show(4)
obj.show(4,5)
Output:
None None
4
4 5
Due to the fact that we sent two parameters 4 and 5 during the function call, two distinct values for a
and b are allocated.
Thus, in the preceding example, we saw how we may utilize the same method and call distinct functions
in a variety of ways.
Consider another example in which we utilized conditional statements to invoke several functions in
distinct ways.
Example:
class Area:
    def find_area(self, a=None, b=None):
        if a != None and b != None:
            print("Rectangle:", (a * b))
        elif a != None:
            print("square:", (a * a))
        else:
            print("No figure assigned")
obj1=Area()
obj1.find_area()
obj1.find_area(10)
obj1.find_area(10,20)
Output:
No figure assigned
square: 100
Rectangle: 200
If no arguments are supplied during the function call, no value is assigned; if a single argument is passed, the area of a square is shown; and if two values are passed, the area of a rectangle is displayed.

Inheritance

Before we get into method overriding, it’s necessary to understand Python’s initial inheritance. Inheritance is the method by which a class may be derived from any base class, with the derived class inheriting all of the base class’s attributes. Inheritance alleviates the challenge of repeatedly writing the same code and enhances reusability.
Example of inheritance:
class Bird://base class Bird
    def sound(self):
        print("Birds Sounds")
#сhild сlаss Dоg inherits the bаse сlаss Аnimаl
class Sparrow(Bird)://child class Sparrow
    def tweet(self):
        print("sparrow tweeting")
d = Sparrow()
d.tweet()
d.sound()
Output:
Sparrow tweeting
Birds Sound

Method Overriding

Method overriding is the process of changing a base class using the methods and parameters of a derived class.
Consider an example to demonstrate how it works. To begin, we’ll design a base class containing a method and then a derived class devoid of methods.
Example:
class Vehicle:
    def run(self):
        print("Saves Energy")
class EV(Vehicle):
    pass
ev = EV()
ev.run()
As a result, when the function is invoked, the output will display the method of the base class, since the derived class lacks a method.
Output:
Saves Energy
Now, in the following example, we define another method with the same name as the base class but with a different parameter under the derived class. Due to the fact that the base class’s method has been overridden by the derived class, the output will include just the derived class’s method.
Example:
class Vehicle:
    def run(self):
        print("Saves Energy")
class EV(Vehicle):
    def run(self):
        print("Run on Electricity")
ev = EV()
ev.run()
Output:
Run on Electricity
Super() Function
Due to the fact that the base class’s method has been overridden, the base class’s method cannot be invoked normally. Thus, in order to invoke the base class method, we must utilize the super function in the overridden method of the derived class.
Example:
class Vehicle:
    def run(self):
        print("Saves Energy")
class EV(Vehicle):
    def run(self):
    super().run()//super function is used to call the method of base class 
        print("Run on Electricity")
ev = EV()
ev.run()
Output:
Saves Energy
Run on Electricity

Duck Typing

Duck typing is a polymorphism notion. The term duck typing is derived from a proverb that says
everything that walks like a duck quacks like a duck, and swims like a duck is referred to like a duck
regardless of the item. In basic terms, it indicates that if anything matches its behavior to another, it
will be considered a member of the category to which it belongs.

Why is polymorphism needed?

When discussing object-oriented programming in Python, the word polymorphism is unavoidably used.
In object-oriented programming, objects must take on a variety of shapes. This characteristic is critical in
software development. The same action may be executed in a variety of ways because of polymorphism.
This notion is often used while discussing loose coupling, dependency injection, and interfaces, among
other things.

Conclusion

As a result, polymorphism simplifies and improves the readability of the code. It also decreases reading difficulty and saves many lines of code. Polymorphism is a very helpful notion in object-oriented programming that can also be used in real-world circumstances. Real World and Polymorphism are, after all, great friends.

The media shown in this article is not owned by Analytics Vidhya and are used at the Author’s discretion.

About the Author

Prashant Sharma

Currently, I Am pursuing my Bachelors of Technology( B.Tech) from Vellore Institute of Technology. I am very enthusiastic about programming and its real applications including software development, machine learning and data science.

Our Top Authors

Download Analytics Vidhya App for the Latest blog/Article

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