Python Polymorphism
Polymorphism
The word polymorphism comes from Greek and means "many forms". In programming, polymorphism means that the same function or method name can behave differently depending on the object or data type it is used with.
You call one name — len(), speak(), operate() — and each type of object responds in its own appropriate way. This makes code more flexible, reusable, and easier to extend, because the calling code does not need to know exactly what kind of object it is working with.
Function Polymorphism
Many of Python's built-in functions work with different data types and automatically adapt their behavior.
Example: The len() Function
len() With a String
Returns the number of characters.
text = "Python Rocks"
print(len(text))
Expected output:
12
The space counts as a character: 6 + 1 + 5 = 12.
len() With a List
Returns the number of items.
colors = ["red", "blue", "green", "yellow"]
print(len(colors))
Expected output:
4
len() With a Dictionary
Returns the number of key–value pairs.
user_info = {
"username": "admin",
"role": "editor",
"active": True
}
print(len(user_info))
Expected output:
3
The function name is the same each time, but what it measures depends on the type of object. This is function polymorphism.
Operator Polymorphism
Operators are polymorphic too. The + operator adds numbers, joins strings, and combines lists:
print(5 + 3)
print("Py" + "thon")
print([1, 2] + [3])
Expected output:
8
Python
[1, 2, 3]
How It Works Behind the Scenes
len(obj) works by calling the object's own special method, obj.__len__(). Each type — str, list, dict — implements __len__() in its own way. Your own classes can do the same:
class Playlist:
def __init__(self, songs):
self.songs = songs
def __len__(self):
return len(self.songs)
my_playlist = Playlist(["Song A", "Song B", "Song C"])
print(len(my_playlist))
Expected output:
3
Because Playlist defines __len__(), the built-in len() function works with it just like it works with lists and strings.
Polymorphism With Classes
In object-oriented programming, polymorphism usually means that several classes have a method with the same name, but each implements it differently.
Example: Different Animals, One Method Name
class Dog:
def speak(self):
print("Dog barks")
class Cat:
def speak(self):
print("Cat meows")
class Bird:
def speak(self):
print("Bird chirps")
animals = [Dog(), Cat(), Bird()]
for animal in animals:
animal.speak()
Expected output:
Dog barks
Cat meows
Bird chirps
Why this is powerful:
- The loop calls
animal.speak()without checking what type of animal it is — there is noif isinstance(animal, Dog): ... elif .... - Each object responds to
speak()in its own way. - Adding a new animal, such as a
Cowclass with its ownspeak()method, requires no changes to the loop.
Duck Typing
Notice that Dog, Cat, and Bird are unrelated classes — they do not share a parent. The loop works simply because each object has a speak() method.
This style is called duck typing, from the saying: "If it walks like a duck and quacks like a duck, it is a duck." Python cares about what an object can do, not what class it belongs to.
If an object in the list did not have a speak() method, Python would raise an AttributeError when the loop reached it.
Polymorphism Through Inheritance
Polymorphism is also commonly used with parent and child classes. Child classes inherit methods from the parent and can override them — replace them with their own versions.
Example: The Base Class
class Appliance:
def __init__(self, name):
self.name = name
def operate(self):
print("Appliance is operating")
The Child Classes
class WashingMachine(Appliance):
def operate(self):
print("Washing clothes")
class Refrigerator(Appliance):
def operate(self):
print("Cooling food")
class Microwave(Appliance):
pass
WashingMachineandRefrigeratoroverrideoperate()with their own behavior.Microwavedoes not defineoperate(), so it inherits the parent's version.
Using Polymorphism
a1 = WashingMachine("LG Washer")
a2 = Refrigerator("Samsung Fridge")
a3 = Microwave("IFB Microwave")
for item in (a1, a2, a3):
print(item.name)
item.operate()
Expected output:
LG Washer
Washing clothes
Samsung Fridge
Cooling food
IFB Microwave
Appliance is operating
How Python chooses which operate() to run:
- For
a1, Python looks inWashingMachinefirst, findsoperate(), and runs it. - For
a2, Python findsoperate()inRefrigerator. - For
a3, Python does not findoperate()inMicrowave, so it continues to the parent classApplianceand runs that version.
All three objects also share the name property set by the inherited __init__().
Practical Example: Payment Methods
Polymorphism is common in real applications. Here, an online store processes different payment types with the same code:
class Payment:
def __init__(self, amount):
self.amount = amount
def pay(self):
raise NotImplementedError("Subclasses must implement pay()")
class CardPayment(Payment):
def pay(self):
print(f"Charged ₹{self.amount} to card")
class UPIPayment(Payment):
def pay(self):
print(f"Requested ₹{self.amount} via UPI")
class CashOnDelivery(Payment):
def pay(self):
print(f"Collect ₹{self.amount} on delivery")
def checkout(payment):
payment.pay()
for method in [CardPayment(1200), UPIPayment(450), CashOnDelivery(999)]:
checkout(method)
Expected output:
Charged ₹1200 to card
Requested ₹450 via UPI
Collect ₹999 on delivery
checkout()works with any payment object that has apay()method.- The base class's
pay()raisesNotImplementedError, which signals that every subclass is expected to provide its own version. - Supporting a new payment type means adding one new class —
checkout()stays unchanged.
Benefits of Polymorphism
- Flexibility — one piece of code works with many different types of objects.
- Extensibility — new classes can be added without modifying existing code.
- Readability — long
if/elifchains that check types are replaced by simple method calls. - Reusability — common interfaces encourage consistent, reusable designs.
Common Mistakes
| Mistake | Problem |
|---|---|
Different method names in related classes (bark(), meow()) | The objects cannot be used interchangeably |
| Different parameters for the same method name | Calls work for some objects but raise TypeError for others |
Checking types with if isinstance(...) everywhere | Defeats the purpose of polymorphism |
| Misspelling an overriding method | The parent's version runs instead |
| An object without the expected method | AttributeError when the method is called |
Related Concepts
- Python Inheritance — overriding methods in child classes
- Python Class Methods — defining behavior in classes
- Python Functions — built-in functions such as
len()that work with many types - Python Encapsulation — hiding implementation details behind a common interface