Python Polymorphism Tutorial | Method Overriding, Operator Overloading & Duck Typing
One of the most powerful features of Object-Oriented Programming is Polymorphism, which means “many forms.” Polymorphism allows the same method, function, or interface to behave differently depending on the object that calls it.
In real-world software development, polymorphism helps developers write flexible, reusable, and maintainable code. Whether you’re building an e-commerce platform, payment gateway, AI application, banking system, or web framework like Django, polymorphism allows different objects to respond differently to the same operation.
In this lesson, you’ll learn how polymorphism works in Python through method overriding, duck typing, operator overloading, and built-in polymorphic functions. You’ll also explore practical examples that demonstrate why polymorphism is one of the most important concepts in Object-Oriented Programming.
By the end of this lesson, you’ll be able to write cleaner, more scalable, and reusable Python applications using polymorphism.
Learning Objectives
After completing this lesson, you will be able to:
- Understand the concept of polymorphism.
- Apply method overriding.
- Understand runtime polymorphism.
- Learn duck typing.
- Perform operator overloading.
- Use built-in polymorphic functions.
- Build scalable applications using polymorphism.
- Apply polymorphism in real-world software.
Topics Covered
- What is Polymorphism?
- Method Overriding
- Runtime Polymorphism
- Duck Typing
- Operator Overloading
- Built-in Polymorphism
- Real-World Applications
- Best Practices
Detailed Lesson Content
Introduction to Polymorphism
Imagine you’re developing an Online Payment System.
Customers can pay using:
- Credit Card
- Debit Card
- UPI
- Net Banking
- Wallet
Although every payment method performs a payment, each one follows a different process.
Instead of creating completely different systems, we define one method called:
make_payment()
Each payment method performs its own implementation.
This is Polymorphism.
The same interface behaves differently depending on the object.
What is Polymorphism?
The word Polymorphism comes from two Greek words:
- Poly → Many
- Morph → Forms
In Python,
One interface, multiple implementations.
Example
A Dog and a Cat both have a method named:
sound()
But:
Dog →
Bark
Cat →
Meow
The method name remains the same.
The behavior changes.
Why Do We Need Polymorphism?
Without polymorphism:
- Large if-else blocks
- Duplicate code
- Difficult maintenance
- Poor scalability
With polymorphism:
- Cleaner code
- Easier maintenance
- Better scalability
- More flexibility
- Better software design
Method Overriding
Method overriding occurs when a child class provides its own implementation of a method already defined in the parent class.
Example
class Animal:
def sound(self):
print("Animal Sound")
class Dog(Animal):
def sound(self):
print("Dog Barks")
dog = Dog()
dog.sound()
Output
Dog Barks
The parent method is overridden by the child class.
Runtime Polymorphism
Python decides which method to execute during runtime.
Example
class Bird:
def fly(self):
print("Bird Flying")
class Eagle(Bird):
def fly(self):
print("Eagle Flying High")
class Sparrow(Bird):
def fly(self):
print("Sparrow Flying")
birds = [Eagle(), Sparrow()]
for bird in birds:
bird.fly()
Output
Eagle Flying High
Sparrow Flying
The same method behaves differently for different objects.
Duck Typing
Python follows the principle:
“If it walks like a duck and quacks like a duck, it’s a duck.”
Python focuses on behavior instead of object type.
Example
class Dog:
def speak(self):
print("Bark")
class Cat:
def speak(self):
print("Meow")
def make_sound(animal):
animal.speak()
make_sound(Dog())
make_sound(Cat())
Output
Bark
Meow
The function doesn’t care about the object type.
It only checks whether the object has a speak() method.
Operator Overloading
Python allows operators to behave differently for different data types.
Example
print(10 + 20)
Output
30
Now with strings
print("Hello " + "World")
Output
Hello World
The + operator performs:
- Addition for numbers
- Concatenation for strings
This is operator overloading.
Magic Methods
Python provides special methods for operator overloading.
Example
class Number:
def __init__(self,value):
self.value = value
def __add__(self,other):
return self.value + other.value
a = Number(10)
b = Number(20)
print(a+b)
Output
30
Python internally calls:
__add__()
Other important magic methods:
__sub__()__mul__()__truediv__()__eq__()__lt__()
Built-in Polymorphism
Python built-in functions also demonstrate polymorphism.
Example
print(len("Python"))
Output
6
Now
print(len([10,20,30]))
Output
3
Same function.
Different behavior.
Real-World Example 1: Payment Gateway
class Payment:
def pay(self):
pass
class UPI(Payment):
def pay(self):
print("Payment through UPI")
class CreditCard(Payment):
def pay(self):
print("Payment through Credit Card")
payments = [UPI(),CreditCard()]
for payment in payments:
payment.pay()
Real-World Example 2: Notification System
class Notification:
def send(self):
pass
class Email(Notification):
def send(self):
print("Email Sent")
class SMS(Notification):
def send(self):
print("SMS Sent")
notifications = [Email(),SMS()]
for item in notifications:
item.send()
Real-World Example 3: AI Chatbots
class AIModel:
def generate(self):
print("Generating Response")
class ChatBot(AIModel):
def generate(self):
print("AI Chatbot Response")
class ImageGenerator(AIModel):
def generate(self):
print("AI Image Generated")
models = [ChatBot(),ImageGenerator()]
for model in models:
model.generate()
Real-World Example 4: Vehicle System
class Vehicle:
def start(self):
pass
class Car(Vehicle):
def start(self):
print("Car Started")
class Bike(Vehicle):
def start(self):
print("Bike Started")
vehicles = [Car(),Bike()]
for vehicle in vehicles:
vehicle.start()
Common Mistakes
Forgetting Method Overriding
If the child class does not redefine the method, the parent implementation will always be used.
Changing Method Parameters
Incorrect
class Animal:
def sound(self):
pass
class Dog(Animal):
def sound(self,name):
The method signature should remain compatible.
Confusing Overloading and Overriding
Python supports:
- Method Overriding ✅
Python does not support traditional Method Overloading like Java or C++.
Best Practices
- Override methods only when behavior changes.
- Keep method names consistent.
- Follow the Liskov Substitution Principle.
- Prefer polymorphism over complex
if-elsechains. - Use duck typing when appropriate.
- Keep implementations simple and readable.
Key Takeaways
- Polymorphism means one interface, many implementations.
- Method overriding is the most common form of polymorphism.
- Duck typing focuses on an object’s behavior, not its type.
- Operator overloading allows operators to work differently for different objects.
- Built-in functions like
len()also demonstrate polymorphism. - Polymorphism makes applications flexible, scalable, and easier to maintain.



