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 in python is a term used 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.
This article was published as a part of the Data Science Blogathon
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)
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.
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.
Two Types of Polymorphism in Python :
Objects are used based on their abilities (methods) and can be of different classes as long as they share the same methods. This is achieved through method overriding in inheritance.
Special methods like __add__ allow for custom behavior when using operators (+, -, etc.) with your objects.
Overloading may be classified into two categories.
Operator overloading is a kind of overloading in which an operator may be used in ways other than
those stated in its predefined definition.
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
class Vehicle:
def __init__(self, fare):
self.fare = fare
bus= Vehicle(20)
car= Vehicle(30)
total_fare=bus+ car
print(total_fare)
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)
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.
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)
True
In the above example, the relational operator __lt__ is utilized as a special function to enable the operator 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.
class A:
def show(self, a=None, b=None):
print(a,b)
obj=A()
obj.show()
None None
To supply another value, I must now use another method obj.show() with an argument.
class A:
def show(self, a=None, b=None):
print(a,b)
obj=A()
obj.show()
obj.show(4)
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.
class A:
def show(self, a=None, b=None):
print(a,b)
obj=A()
obj.show()
obj.show(4)
obj.show(4,5)
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.
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)
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.
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.
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()
Sparrow tweeting
Birds Sound
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.
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.
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.
class Vehicle:
def run(self):
print("Saves Energy")
class EV(Vehicle):
def run(self):
print("Run on Electricity")
ev = EV()
ev.run()
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.
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()
Saves Energy Run on Electricity
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.
When discussing object-oriented programming in Polymorphism 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.
Polymorphism in Python offers versatility through different types like Duck Typing, Limited Operator Overloading, and various techniques like Overloading, Operator Overloading, Method Overloading, Inheritance, and Method Overriding. It’s vital for flexible, reusable code, allowing objects to be treated interchangeably, and enhancing code readability and maintainability.
Polymorphism in programming means objects can do different things based on how they’re used. In Python, it lets different types of objects work together if they have similar traits.
In Python, polymorphism is like having objects in a box (encapsulation) and sharing traits (inheritance). Encapsulation keeps things organized, and inheritance lets objects borrow traits from others.
In Python, overloading means having different versions of a function with the same name but different arguments. Overriding happens when a subclass changes how a method works that it got from its parent class. It helps objects act differently based on their type.