Polymorphism is one of the most powerful and fundamental concepts in Object-Oriented Programming (OOP). In simple terms, polymorphism allows objects of different classes to be treated as objects of a common superclass. This enables a single interface to represent different underlying forms (data types).
In Python, polymorphism makes code more flexible, reusable, and easier to maintain. This concept is commonly used in inheritance, method overriding, and operator overloading. In this article, we will explore what polymorphism is, how it works in Python, and how to implement it with real-world examples and complete code snippets.

What Is Polymorphism in Python?
The word “polymorphism” comes from Greek words poly (many) and morph (forms). In programming, polymorphism means the same function name can be used for different types or classes. It allows one function or method to work in multiple ways depending on the object that calls it.
Example of Built-in Polymorphism in Python
Python supports polymorphism in many of its built-in functions. For example, the function len() can be used for strings, lists, tuples, or dictionaries — each producing a result appropriate to its type.
# Example of built-in polymorphism
print(len("Python")) # Output: 6 (string)
print(len([1, 2, 3])) # Output: 3 (list)
print(len({"a": 1, "b": 2})) # Output: 2 (dictionary)
This is an example of polymorphism where the same function (len()) behaves differently depending on the input type.
Polymorphism with Class Methods
In Python OOP, polymorphism is often implemented using class inheritance and method overriding. Different classes can have methods with the same name, but their implementation can differ according to the class needs.
Example: Animal Sounds
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
# Using polymorphism
animals = [Dog(), Cat()]
for animal in animals:
print(animal.speak())
Explanation: The speak() method is defined in the parent class Animal but implemented differently in each subclass. When we iterate through the animals list, the correct method is automatically called depending on the object type. This is the essence of polymorphism.
Polymorphism with Inheritance and Method Overriding
When a subclass provides a specific implementation for a method already defined in its superclass, it is called method overriding. Python automatically determines which method to use at runtime, depending on the object type.
Example: Vehicle Example
class Vehicle:
def move(self):
print("Vehicles can move")
class Car(Vehicle):
def move(self):
print("Cars drive on the road")
class Boat(Vehicle):
def move(self):
print("Boats sail on water")
class Plane(Vehicle):
def move(self):
print("Planes fly in the sky")
vehicles = [Car(), Boat(), Plane()]
for v in vehicles:
v.move()
This example shows that move() behaves differently depending on the subclass, even though they share the same method name. This is runtime polymorphism in action.
Polymorphism with Functions and Objects
Python’s dynamic typing allows you to use polymorphism even without inheritance. Any object that implements the required behavior can be used interchangeably — this concept is known as duck typing.
Example of Duck Typing
class Bird:
def fly(self):
print("Birds can fly")
class Airplane:
def fly(self):
print("Airplanes can also fly")
class Fish:
def swim(self):
print("Fish can swim")
def lift_off(entity):
entity.fly()
bird = Bird()
plane = Airplane()
lift_off(bird)
lift_off(plane)
Output:
Birds can fly Airplanes can also fly
Even though Bird and Airplane have no common parent class, Python allows them to be used polymorphically as long as they have the same method (fly()). This flexibility is a key feature of Python’s polymorphism.
Operator Overloading (Another Form of Polymorphism)
Polymorphism can also occur when operators like + or * are used with different data types. Python internally calls special methods such as __add__() or __mul__() to handle these operations.
Example: Operator Overloading
class Book:
def __init__(self, pages):
self.pages = pages
def __add__(self, other):
return self.pages + other.pages
book1 = Book(200)
book2 = Book(350)
print(book1 + book2) # Output: 550
Here, the + operator is overloaded to add the number of pages of two Book objects, instead of performing the default addition operation.
Why Polymorphism Is Important
- Flexibility: You can write code that works with multiple object types.
- Reusability: Methods can be reused without rewriting logic for each new class.
- Clean Code: Enhances readability and reduces redundant code.
- Extensibility: Easier to add new features by extending existing classes.
Real-World Example: Payment System
Let’s see a simple real-world example where polymorphism can be useful in a payment system supporting different methods like Credit Card, PayPal, and Crypto.
class Payment:
def pay(self):
pass
class CreditCard(Payment):
def pay(self):
return "Payment processed using Credit Card."
class PayPal(Payment):
def pay(self):
return "Payment processed using PayPal."
class Crypto(Payment):
def pay(self):
return "Payment processed using Cryptocurrency."
def process_payment(payment_method):
print(payment_method.pay())
methods = [CreditCard(), PayPal(), Crypto()]
for method in methods:
process_payment(method)
This example shows how you can handle multiple payment methods through a single interface, thanks to polymorphism. Adding a new payment type in the future would not require modifying the existing payment processing logic.
Conclusion
Polymorphism in Python allows developers to design flexible and scalable code structures. Whether you are using inheritance, method overriding, or duck typing, polymorphism simplifies your code and promotes reusability. It’s an essential concept to master when working with object-oriented programming in Python.
By understanding polymorphism, you can write cleaner, more maintainable, and more adaptable Python code suitable for real-world software development.