Beginner Level
Intermediate Level
Advanced Level
Introduction
One of Python's key features is its support for object-oriented programming (OOP) concepts such as polymorphism. Polymorphism is a technique that allows different objects to be treated in a similar way as they share a common interface. This means that developers can write code that works with a variety of different data types in a single, unified way. This tutorial will explore the concept of polymorphism in Python, how it works and how it can be used in real-world applications.
Table of Contents :
- Polymorphism in Python
- Method Overriding
- Method Overloading
- using default arguments or
- using variadic functions
- using keyword arguments
- using @dispatch decorator
- Duck Typing
- Operator Overloading
Polymorphism in Python :
- Polymorphism is the ability of an object to take on different forms.
- Python is an object-oriented programming language.
- This means that every value in Python is an object, and every object has a type.
- For example,
- the integer 1 is an object with the type int,
- the string "hello" is an object with the type str, and
- the list [1, 2, 3] is an object with the type list.
- Objects can have different types depending on their value.
- In Python, this means that an object can be of more than one type.
- For example, the integer 1 is also an object with the type float. This is because Python automatically converts integers to floats when they are used in a float context.
- Similarly, the string "hello" is also an object with the type list. This is because Python automatically converts strings to lists when they are used in a list context.
- Polymorphism is a powerful feature of Python that allows for great flexibility in how objects are used.
- Polymorphism is the ability for objects of different classes to be treated as if they are of the same class.
- In Python, we can implement polymorphism through
- method overriding and
- method overloading.
Method Overriding:
- Method overriding allows a sub-class to provide a different implementation of a method that is already defined in its super-class.
- It is achieved by defining a method with the same name in the sub-class as in the super-class.
- The sub-class method will be called instead of the super-class method when a method is called on an instance of the sub-class.
- Code Sample :
class Animal:
def speak(self):
print("Animal speaks")
class Dog(Animal):
def speak(self):
print("Dog barks")
class Cat(Animal):
def speak(self):
print("Cat meows")
a = Animal()
a.speak()
d = Dog()
d.speak()
c = Cat()
c.speak()
# Output
# Animal speaks
# Dog barks
# Cat meows
Method Overloading :
- Method overloading allows methods with the same name to have different signatures or parameters.
- Python does not support method overloading by default.
- We can define two or more methods with same name in python but it will use the method defined at last.
- But we can achieve method overloading in python by using any of the following methods :
- using default arguments or
- using variadic functions (*args)
- using keyword arguments (**kwargs)
- using @dispatch decorator
Method Overloading using default arguments :
- We can give a default value to some of the arguments of the function that we want to overload.
- Because of the default value we can pass different number of arguments while calling the function, thus overloading the function.
- Code Sample :
class Calculator:
def add(self, x, y, z=0):
return x + y + z
c = Calculator()
sum_2 = c.add(6, 7)
sum_3 = c.add(2, 3, 4)
print(f"The sum of three numbers = {sum_3}")
print(f"The sum of two numbers = {sum_2}")
# Output
# The sum of three numbers = 9
# The sum of two numbers = 13
Method Overloading using variadic functions :
- Functions with *args as one of the parameter are known as variadic functions.
- We know that variadic functions can take variable number of arguments.
- This feature of variadic functions to take variable number of arguments can be used to overload functions.
- Code Sample :
class Calculator:
def add(self, x, y, *args):
l = len(args)
if l > 0:
return x + y + args[0]
else:
return x + y
c = Calculator()
sum_2 = c.add(6, 7)
sum_3 = c.add(2, 3, 4)
print(f"The sum of three numbers = {sum_3}")
print(f"The sum of two numbers = {sum_2}")
# Output
# The sum of three numbers = 9
# The sum of two numbers = 13
Method Overloading using keyword arguments :
- We can use keyword arguments to overload functions in python.
- We know that functions with keyword arguments can take variable number of arguments.
- This method of passing variable number of arguments can be used to overload functions.
- Code Sample :
class Calculator:
def add(self, x, y, **kwargs):
if 'z' in kwargs:
return x + y + kwargs["z"]
else:
return x + y
c = Calculator()
sum_2 = c.add(x=6, y=7)
sum_3 = c.add(x=2, y=3, z=4)
print(f"The sum of three numbers = {sum_3}")
print(f"The sum of two numbers = {sum_2}")
# Output
# The sum of three numbers = 9
# The sum of two numbers = 13
Method Overloading using dispatch decorator :
- to overload functions in python we can use the
@dispatch
decorator. - To use the
@dispatch
decorator we first need to install a module calledmultipledispatch
- We can install the
multipledispatch
module using pip :pip3 install multipledispatch
- Dispatcher internally creates an object that saves different implementations of the function.
- At runtime it matches the number and type of parameters and invokes the appropriate method.
- Code Sample :
from multipledispatch import dispatch
@dispatch(int, int)
def add(num_1, num_2):
result = num_1 + num_2
return result
@dispatch(int, int, int)
def add(num_1, num_2, num_3):
result = num_1 + num_2 + num_3
return result
@dispatch(float, float, float)
def add(num_1, num_2, num_3):
result = num_1 + num_2 + num_3
return result
# calling product method with 2 arguments
res = add(5, 4)
print(f"The sum of two numbers = {res}")
# calling product method with 3 arguments but all int
res = add(5, 4, 2)
print(f"The sum of three numbers = {res}")
# calling product method with 3 arguments but all float
res = add(5.1, 4.31, 2.6)
print(f"The sum of three float numbers = {res}")
# Output
# The sum of two numbers = 9
# The sum of three numbers = 11
# The sum of three float numbers = 12.01
Duck Typing :
- Duck typing is a concept in Python where the type or class of an object is less important than the methods it defines.
- It allows different types of objects to be treated similarly if they have similar methods or attributes.
- Code Sample :
class Duck:
def quack(self):
print("Quack quack")
class Person:
def quack(self):
print("I can't quack like a duck, but I can mimic it")
def duck_quack(obj):
obj.quack()
d = Duck()
p = Person()
# Both the Duck and Person objects can be passed to the duck_quack() function
duck_quack(d)
duck_quack(p)
# Output
# Quack quack
# I can't quack like a duck, but I can mimic it
Operator Overloading :
- Operator overloading allows the operators such as +, -, *, /, ==, <, >, etc. to be treated differently depending on the data type of operands.
- It is achieved by defining special functions that Python uses for these operators, such as
- __add__
- __sub__
- __mul__
- __eq__
- __lt__
- __gt__ etc.
- Code Sample :
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
v1 = Vector(2, 3)
v2 = Vector(4, 5)
v3 = v1 + v2
print(v3.x, v3.y)
# Output:
# 6 8
Prev. Tutorial : Encapsulation
Next Tutorial : Inheritance