Saturday, January 16, 2021

Polymorphism in Python

Polymorphism is one of the four fundamental OOPS concepts. The other three being Inheritance, Encapsulation, Abstraction

Polymorphism is a Greek word where poly means many and morph means change thus it refers to the ability of an entity taking many forms. In an object oriented context that means an entity which may be a method, object or operator can represent different types based on the scenario where they are used.

Polymorphism in Python

In an object oriented language you will find support for Polymorphism through-

  • Method overloading
  • Method overriding
  • Operator overloading

Python being an object oriented language also supports Polymorphism but only through Method overriding and operator overloading. Method overloading in its traditional sense is not supported in Python.

Apart from these ways you will also find support for Polymorphism in Python through duck typing. If there is an object that can fly and quack like a duck then it must be a duck, this is the duck typing principle followed in Python.

In this post we’ll see examples of polymorphism in Python through all these options.


Python Polymorphism example- Method overloading

Method overloading in its traditional sense, where you can have more than one method having the same name with in the class where the methods differ in types or number of arguments passed, is not supported in Python.

Trying to have methods with same name won’t result in compile time error in Python but only the last defined method is recognized in such scenario, calling any other overloaded method results in an error.

But you can still simulate polymorphism through method overloading by using default arguments in a method. In the example there is one default argument in the method sum. If the method is called with 2 parameters for the third default value is used. If the method is called with 3 parameters passed value is used for the third parameter.

class OverloadDemo:
  # sum method with one default parameter
  def sum(self, a, b, c=0):
    s = a + b + c
    return s

od =  OverloadDemo()
#calling method with 2 args
sum = od.sum(7, 8)
print('sum is-', sum)
#calling method with 3 args
sum = od.sum(7, 8, 9)
print('sum is-', sum)

Output

sum is- 15
sum is- 24 

Polymorphism through inheritance- Method overriding

Method overriding provides ability to change the implementation of a method in a child class which is already defined in one of its super class. If there is a method in a super class and method having the same name and same number of arguments in a child class then the child class method is said to be overriding the parent class method.

When the method is called with parent class object, method of the parent class is executed. When method is called with child class object, method of the child class is executed. So the appropriate overridden method is called based on the object type, which is an example of Polymorphism.

Polymorphism through inheritance example

class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  def displayData(self):
    print('In parent class displayData method')
    print(self.name)
    print(self.age)

class Employee(Person):
  def __init__(self, name, age, id):
    # calling constructor of super class
    super().__init__(name, age)
    self.empId = id

  def displayData(self):
    print('In child class displayData method')
    print(self.name)
    print(self.age)
    print(self.empId)

#Person class object
person = Person('John', 40)
person.displayData()
#Employee class object
emp = Employee('John', 40, 'E005')
emp.displayData()

Output

In parent class displayData method
John
40
In child class displayData method
John
40
E005

In the example when the displayData() method is called with Person class object, displayData() of the Person class is executed. When displayData() method is called with Employee class object, displayData() of the Employee class is executed.

Polymorphism through operator overloading

Operator overloading means the ability to overload the operator to provide extra functionality in addition to its real operational meaning. Operator overloading is also an example of polymorphism as the same operator can perform different actions.

For example ‘+’ operator which is used with numbers to perform addition operation. But ‘+’ operator when used with two strings concatenate those Strings and merge two lists when used with lists in Python.

#using + operator with integers to add them
print(5 + 7)
#using + operator with Strings to concatenate them
print('hello ' + 'world')
a = [1, 2, 3]
b = [4, 5, 6]
# using + operator with List to concatenate them
print(a + b)

Output

12
hello world
[1, 2, 3, 4, 5, 6]

You can also overload operators to provide functionality for custom class objects. For all operators internally Python defines methods to provide functionality for those operators. For example functionality for ‘+’ operator is provide by special method __add__(). Whenever ‘+’ operator is used internally __add__() method is invoked to do the operation.

When you want any operator to work with custom objects you need to override the corresponding special method that provides functionality for that operator.

Overloading ‘+’ operator to work with custom objects

class Point:
  def __init__(self, x, y):
    self.x = x
    self.y = y
  #overriding magic method
  def __add__(self, other):
    return self.x + other.x, self.y + other.y

p1 = Point(1, 2)
p2 = Point(3, 4)

print(p1+p2)

Output

(4, 6)

Duck typing in Python

Python though strongly typed is also dynamically typed so the type of any object/field is implicitly assigned depending on where and how the field is used.

If there is an object that can fly and quack like a duck then it must be a duck, this is duck typing principle followed in Python.

When you invoke a method using an object type of the object is not checked in Python. You can use any object to invoke a method as long as that method is there to be invoked.

class Duck:
  def sound(self):
    print('Quack Quack')

class Cat:
  def sound(self):
    print('Meow Meow')

class Human:
  def sound(self):
    print('Hey hello')

class Test:
  def invoke(self, obj):
    obj.sound();

t = Test()
obj = Duck()
t.invoke(obj)

obj = Cat()
t.invoke(obj)

obj = Human()
t.invoke(obj)

Output

Quack Quack
Meow Meow
Hey hello

When the object of type Cat is passed to the invoke() method and sound() method is called using that object, sound() method of class Cat is executed. When object of type Duck is passed to the invoke() method and sound() method is called using that object, sound() method of class Duck is executed and same for object of type Human.

As evident from the example because of the duck typing philosophy of Python you are getting run time polymorphism inbuilt with in the language, based on the passed object correct method is invoked at runtime.

That's all for this topic Polymorphism in Python. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Python Tutorial Page


Related Topics

  1. Interface in Python
  2. Abstract Class in Python
  3. Namespace And Variable Scope in Python
  4. Python First Program - Hello World
  5. Python while Loop With Examples

You may also like-

  1. Class And Object in Python
  2. String Slicing in Python
  3. Python Program to Reverse a String
  4. Concatenating Lists in Python
  5. Nested Class And Inner Class in Java
  6. Why no Multiple Inheritance in Java
  7. Introduction to Hadoop Framework
  8. Setter-Based Dependency Injection in Spring