Polymorphism means:
"Same interface, different behavior"
👉 One name → Many forms
Instead of worrying about what type an object is,
we care about what behavior it provides.
Polymorphism allows:
✔ Different objects
✔ Same method name
✔ Different implementations
Example:
Dog → speak()
Cat → speak()
Human → speak()
All respond to:
speak()
class Dog:
def speak(self):
print("Woof")
class Cat:
def speak(self):
print("Meow")
animals = [Dog(), Cat()]
for animal in animals:
animal.speak()Output:
Woof
Meow
✔ Same method name → speak()
✔ Different behavior → depends on object
Python decides at runtime.
✔ Flexible code
✔ No type checking needed
✔ Extensible systems
✔ Cleaner architecture
✔ Plug-and-play behavior
Python polymorphism relies heavily on:
Duck Typing
Rule:
"If it behaves like a duck → it's a duck"
👉 Type does NOT matter
👉 Behavior matters
class Dog:
def speak(self):
print("Woof")
class Robot:
def speak(self):
print("Beep")
def make_it_speak(entity):
entity.speak()
make_it_speak(Dog())
make_it_speak(Robot())Output:
Woof
Beep
✔ No inheritance required
Many built-ins are polymorphic:
print(len("Hello")) # String
print(len([1, 2, 3])) # List
print(len((1, 2))) # Tuple✔ Same function → Different objects
Classic OOP polymorphism:
class Animal:
def speak(self):
print("Animal sound")
class Dog(Animal):
def speak(self):
print("Woof")
class Cat(Animal):
def speak(self):
print("Meow")
animals = [Dog(), Cat()]
for animal in animals:
animal.speak()✔ Method overriding
Python determines behavior using:
Dynamic Dispatch
✔ Happens at runtime
✔ Based on object type
class Payment:
def pay(self, amount):
pass
class CreditCard(Payment):
def pay(self, amount):
print(f"Paid {amount} using Credit Card")
class UPI(Payment):
def pay(self, amount):
print(f"Paid {amount} using UPI")
def process_payment(method, amount):
method.pay(amount)
process_payment(CreditCard(), 1000)
process_payment(UPI(), 500)✔ Same interface → Multiple implementations
Python encourages:
Behavior-based polymorphism
class Bird:
def move(self):
print("Flying")
class Fish:
def move(self):
print("Swimming")
def make_it_move(creature):
creature.move()
make_it_move(Bird())
make_it_move(Fish())✔ Pure duck typing
Python does NOT enforce interfaces.
def make_it_speak(entity):
entity.speak()If missing:
AttributeError
Polymorphism is NOT about inheritance.
✔ It's about shared behavior.
Bad design:
if isinstance(obj, Dog):
...✔ Breaks polymorphism
Better:
obj.speak()class Dog:
def speak(self): pass
class Robot:
def speak(self, volume): pass✔ Runtime error risk
Keep interface consistent.
Duck typing can hide errors:
✔ Wrong method → No immediate crash
✔ Logic failure 😱
✔ Design around behavior
✔ Keep method names consistent
✔ Avoid explicit type checking
✔ Prefer duck typing
✔ Use ABCs for strict contracts
✔ Keep interfaces stable
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def speak(self):
pass✔ Enforces contract
Polymorphism enables:
✔ Strategy Pattern
✔ Plugin Systems
✔ Dependency Injection
✔ Flexible APIs
✔ Clean Architecture
✔ Polymorphism = Same interface, different behavior
✔ Python → Duck typing driven
✔ No inheritance required
✔ Runtime behavior resolution
✔ Extremely flexible design
✔ Dangerous if misunderstood
- Create multiple classes sharing same method
- Use duck typing without inheritance
- Break polymorphism using isinstance()
- Fix using pure behavior calls
- Create payment strategy system
- Cause signature mismatch bug
- Fix interface consistency