Skip to main content

Python Polymorphism

Polymorphism in Python is a principle of object-oriented programming that allows methods, functions, or operators to perform different actions based on the type of the input.

What is Polymorphism in Python?

Polymorphism allows the same method name to be used across different classes, with each class providing its own implementation of the method.

The key difference is the data types and number of arguments used in function. This means that the same function name can be used for different types of operations, as long as the argument types and the number of arguments match the function signature that we want to invoke.

There are two main types of polymorphism in Python:

  1. Function Polymorphism
  2. Class Polymorphism

1. Function Polymorphism in Python

Function Polymorphism is the ability of certain built-in functions in Python to run on different types of objects given as arguments.

A great example of this is the len() function, which can be used with various data types such as strings, lists, and tuples to return the length of the object

print(len("TutorialReference"))
print(len(["Python", "Java", "JavaScript", "C#"]))
print(len({"Name": "Tom", "State": "New York"}))

Output:

17
4
2
note

Notice that many data types (such as string, list, tuple, set, and dictionary) can work with the len() function.

However len() function returns specific information about specific data types. Actually:

  • len(str) returns the length of the string
  • len(list) returns the number of items of the list
  • len(dict) returns the number of keys of the dictionary

2. Class Polymorphism in Python

Class Polymorphism is the ability of different classes to implement the same method name, even though the method may perform different actions depending on the class it is called upon.

note

This concept is closely related to the principle of inheritance, where a child class can override a method from its parent class, which is known as method overriding.

Discover more about Python Inheritance.

For example, let's create two classes Cat and Dog that share a similar structure and have the same method names info() and make_sound().

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

def info(self):
print(f"I am a cat. My name is {self.name}. I am {self.age} years old.")

def make_sound(self):
print("Meow")


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

def info(self):
print(f"I am a dog. My name is {self.name}. I am {self.age} years old.")

def make_sound(self):
print("Bark")


cat1 = Cat("Luna", 3)
dog1 = Dog("Charlie", 5)

for animal in (cat1, dog1):
animal.make_sound()
animal.info()
animal.make_sound()

Output:

Meow
I am a cat. My name is Luna. I am 3 years old.
Meow
Bark
I am a dog. My name is Charlie. I am 5 years old.
Bark
note

We have not created a common superclass or linked the classes together in any way. Even then, we can pack these two different objects into a tuple and iterate through it using a common animal variable.

This is possible thanks to polymorphism!

Relation between Polymorphism and Inheritance in Python

In Python, inheritance is a mechanism that allows a new class (child class) to inherit properties and behaviors from an existing class (parent class). This relationship is established through the syntax class ChildClass(ParentClass), where ChildClass can access all the attributes and methods from the ParentClass.

On the other hand, Polymorphism allows objects of different classes to be treated as objects of a common superclass. This means that the same method can be called on different objects, and the appropriate version of the method will be executed based on the actual type of the object at runtime

The relationship between polymorphism and inheritance in Python is that inheritance provides the basis for polymorphism. When a child class overrides a method from its parent class, it's an example of method overriding, which is a form of polymorphism. The child class's method becomes the default implementation, and it can be further specialized by any further descendant classes.

For example:

from math import pi


class Shape:
def __init__(self, name):
self.name = name

def area(self):
pass

def fact(self):
return "This is a two-dimensional shape."

def __str__(self):
return self.name


class Square(Shape):
def __init__(self, length):
super().__init__("Square")
self.length = length

def area(self):
return self.length**2

def fact(self):
return "Squares have each angle equal to 90 degrees."


class Circle(Shape):
def __init__(self, radius):
super().__init__("Circle")
self.radius = radius

def area(self):
return pi*self.radius**2


square_obj = Square(4)
circle_obj = Circle(7)
print(circle_obj)
print(circle_obj.fact())
print(square_obj.fact())
print(circle_obj.area())

Output:

Circle
This is a two-dimensional shape.
Squares have each angle equal to 90 degrees.
153.93804002589985

Notice that in this example:

  • Methods like __str__(), which have not been overridden in the child classes, are used from the parent class.
  • Thanks to polymorphism, the Python interpreter automatically identifies that the fact() method for object square_obj (which an instance of the Square class) has been overridden by a subclass. Consequently, it uses the overridden version defined in the subclass.
  • The fact() method for object circle_obj isn't overridden and it is uses the implementation provided in the Parent Shape class.
danger

Method Overloading is a way to create multiple methods with the same name but different arguments.

Method Overloading is NOT possible in Python.

But you can do Operator Overloading.