Dremendo Tag Line

Polymorphism in Python Programming

OOPs in Python

In this lesson, we will understand what is Polymorphism in Python and how to implement them in programming along with some examples.

What is Polymorphism in Python?

The term Polymorphism has been derived from the words poly means many and morphism means form. In programming, polymorphism means to create many forms from one.

There are three types of polymorphism available in python and they are:

  • Method Overloading
  • Method Overriding
  • Operator Overloading

Let's discuss each of them in detail one by one.

video-poster

Method Overloading

Method Overloading is a process in which we declare a method that can perform a different task when provided with a different number of inputs.

For example, we will overload a method called area, which, when called with one argument, will display the area of a square. When the same method is called with two arguments, it will display the area of a rectangle.

Example of Method Overloading

class Shape:
    def area(self, x=None, y=None):

        if x!=None and y==None:
            print('Area of a square = %.2f' %(x*x))

        elif x!=None and y!=None:
            print('Area of a rectangle = %.2f' %(x*y))


x = Shape()
x.area(10)
x.area(10,5)

Output

Area of a square = 100.00
Area of a rectangle = 50.00

In the above program, None is a default value for the arguments x and y. When we call the method with one argument, it checks if the value of argument x is not None and the value of argument y is None. If both conditions are true, it prints a square's area.

On the other hand, when we call the method with two arguments, it checks if the value of both the arguments x and y is not None. If the conditions are true, it prints the rectangle's area.

Method Overriding

Method Overriding is a process used in inheritance in which a base class method is redeclared with a new body in a subclass.

Example of Method Overriding

class Student:
    def display(self):
        print('Roll: 1')
        print('Name: Thomas')

class Marks(Student):
    # Overriding the display method of base class in subclass
    def display(self):
        print('English: 82')
        print('Maths: 94')
        print('Computer: 88')


x = Marks()
x.display()

Output

English: 82
Maths: 94
Computer: 88

In the above program, we have created a method called display in the base class Student that prints the roll and name of a student on the screen. On the other hand, we have created another class called Marks that inherits the base class Student. In the subclass Marks, we have overridden the method display of the base class with a new body that prints the marks of three subjects on the screen.

Operator Overloading

Operator Overloading is a process in which we define a new action for an existing operator.

For example, + operator is used for adding two or more numbers. We can define a new action for the + operator so that it can add values stored inside two objects. Doing so means that we have overloaded the + operator.

In python, each operator is associated with an internal method that operates when we use the operator.

For example, + operator is associated with the internal method __add__(self, other), sometimes called the magic method. So when we use the + operator on two variables, say x, y, to find its sum, the magic method of the + operator gets invoked on these variables as x.__add__(y).

List of operators and their magic methods in python

Operator Name Magic Method
+ Addition __add__(self, other)
- Subtraction __sub__(self, other)
* Multiplication __mul__(self, other)
/ Division __div__(self, other)
// Floor Division __floordiv__(self, other)
% Modulus Division __mod__(self, other)
** Power __pow__(self, other)
+= Add and Assign __iadd__(self, other)
-= Subtract and Assign __isub__(self, other)
*= Multiply and Assign __imul__(self, other)
/= Divide and Assign __idiv__(self, other)
//= Floor Divide and Assign __ifloordiv__(self, other)
%= Modulus Divide and Assign __imod__(self, other)
**= Power and Assign __ipow__(self, other)
< Less than __lt__(self, other)
<= Less than or equal to __le__(self, other)
> Greater than __gt__(self, other)
>= Greater than or equal to __ge__(self, other)
== Equal to __eq__(self, other)
!= Not equal to __ne__(self, other)

Overloading + Operator

class Data:

    def __init__(self, a=0, b=0):
        self.x = a
        self.y = b

    def __add__(self, other):
        a = self.x + other.x
        b = self.y + other.y
        return a, b


d1 = Data(10, 20)
d2 = Data(30, 40)
d3 = d1 + d2
print(d3)

Output

(40, 60)

In the above program, we have overloaded the + operator to find the sum of values stored in two objects. Here d1 and d2 are the two objects of class Data. When we call the + operator on d1 + d2 it invokes the __add__(self, other) magic method as d1.__add__(d2). Where self points to the d1 object and other points to the d2 object. Then using self and other as a reference to the objects d1 and d2, we store the sum of their variables in a and b and then return these variables as output.

Overloading += Operator

class Data:

    def __init__(self, a=0, b=0):
        self.x = a
        self.y = b

    def __iadd__(self, other):
        self.x = self.x + other
        self.y = self.y + other
        return self

    def display(self):
        print('x=%d' %(self.x))
        print('y=%d' %(self.y))


d1 = Data(10, 20)
d1.display()
d1+=2
d1.display()

Output

x=10
y=20
x=12
y=22

Overloading > Operator

class Data:

    def __init__(self, a=0):
        self.x = a

    def __gt__(self, other):
        a = self.x > other.x
        return a


d1 = Data(18)
d2 = Data(11)
if d1>d2:
    print('Value of d1 is greater than value of d2')
else:
    print('Value of d1 is not greater than value of d2')

Output

Value of d1 is greater than value of d2