In simple terms, it allows you to use a single function, method, or operator to behave differently based on the type of object it acts upon.
Understanding Polymorphism
In Python, polymorphism is achieved through dynamic typing — meaning you don't need to explicitly declare types. A function can accept different kinds of objects and behave appropriately based on their type.Example:
class Dog:
def sound(self):
return "Bark"
class Cat:
def sound(self):
return "Meow"
# Common interface
def make_sound(animal):
print(animal.sound())
dog = Dog()
cat = Cat()
make_sound(dog)
make_sound(cat)
Output:
Bark
Meow
Here, both Dog and Cat have a sound() method, but the implementation differs. The function make_sound() works for both — that's polymorphism in action!
Duck Typing in Python
Duck typing is a concept closely related to polymorphism. The idea comes from the phrase: "If it walks like a duck and quacks like a duck, it's a duck."This means Python doesn't care about an object's class, only about whether it has the required behavior (methods/attributes).
Example:
class Duck:
def talk(self):
print("Quack, Quack!")
class Human:
def talk(self):
print("Hello there!")
def call_talk(obj):
obj.talk() # Doesn't matter what obj is, as long as it has talk()
duck = Duck()
person = Human()
call_talk(duck)
call_talk(person)
Output:
Quack, Quack!
Hello there!
Here, Duck and Human are completely different classes, but since both define a talk() method, the same function can call them — demonstrating duck typing.
Method Overriding
Method overriding occurs when a derived (child) class defines a method with the same name as one in its base (parent) class, but with a different implementation. This allows subclasses to provide their own version of a method.Example:
class Vehicle:
def start(self):
print("Starting the vehicle...")
class Car(Vehicle):
def start(self):
print("Starting the car engine...")
v = Vehicle()
v.start()
c = Car()
c.start()
Output:
Starting the vehicle...
Starting the car engine...
Here, the start() method is overridden in the Car class to provide specialized behavior.
Method Overloading (Conceptual in Python)
Unlike some other languages (like Java or C++), Python does not support method overloading directly — you can't define multiple methods with the same name but different parameters. However, you can achieve similar functionality using default arguments or variable-length arguments.Example:
class Calculator:
def add(self, a=None, b=None, c=None):
if a is not None and b is not None and c is not None:
return a + b + c
elif a is not None and b is not None:
return a + b
else:
return a
calc = Calculator()
print(calc.add(2, 3))
print(calc.add(2, 3, 5))
Output:
5
10
Here, a single method add() behaves differently depending on how many arguments are passed — mimicking method overloading.
Operator Overloading
Operator overloading is another form of polymorphism where operators like +, -, and * behave differently based on operand types. Python achieves this through special methods like add(), sub(), etc.Example:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
p1 = Point(2, 3)
p2 = Point(4, 5)
result = p1 + p2
print(result.x, result.y)
Output:
6 8
Here, the + operator is “overloaded” to add two Point objects by defining the add() method.
Summary
Polymorphism makes Python code flexible, extensible, and elegant. Whether through method overriding, duck typing, or operator overloading, it allows one interface to serve multiple data types and classes.| Concept | Description |
|---|---|
| Polymorphism | Ability of different classes to be treated as the same type through a common interface |
| Duck Typing | Behavior-based typing — if an object has required methods, its actual class doesn’t matter |
| Method Overriding | Redefining a method in a derived class |
| Method Overloading | Same method name, different arguments (simulated via default parameters or *args) |
| Operator Overloading | Using special methods like __add__() to redefine operators |