Unit 5 · Advanced Topics
Polymorphism
Polymorphism is a core concept of Object-Oriented Programming that allows objects of different classes to be treated through a unified interface, enabling a single function, method, or operator to work with multiple data types.
Table of Contents
University Definition
Polymorphism (from Greek: "many forms") is the ability of a single interface to represent different underlying data types. In Python, polymorphism allows the same function or method name to work with objects of different classes, and the correct version is determined at runtime.
Polymorphism is mainly of two types:
- Compile-time (Static) Polymorphism — Achieved through method/function overloading. Python does not support traditional overloading.
- Runtime (Dynamic) Polymorphism — Achieved through method overriding and duck typing. This is the primary form in Python.
Polymorphism
|
├── Method Overriding (Runtime)
├── Duck Typing (Runtime)
├── Operator Overloading (Compile-time via dunder methods)
└── Function Overloading (via default arguments)
1. Method Overriding (Runtime Polymorphism)
When a child class redefines a method from its parent, the correct method is called based on the object's actual type at runtime. This is the most common form of polymorphism in Python.
class Animal: def sound(self): return "Some generic sound" class Dog(Animal): def sound(self): return "Bark" class Cat(Animal): def sound(self): return "Meow" class Bird(Animal): def sound(self): return "Chirp" # Polymorphism in action — same function, different behavior animals = [Dog(), Cat(), Bird(), Animal()] for animal in animals: print(animal.sound()) # Output: Bark, Meow, Chirp, Some generic sound
2. Duck Typing
University Definition
Duck Typing is a concept where the type or class of an object is less important than the methods and properties it defines. If an object has the required methods, it can be used — regardless of its actual class. The name comes from the phrase: "If it walks like a duck and quacks like a duck, it must be a duck."
class Car: def start(self): return "Car engine started" class Bike: def start(self): return "Bike engine started" class Boat: def start(self): return "Boat engine started" # No common parent — but all have start() def ignite(vehicle): print(vehicle.start()) ignite(Car()) # Car engine started ignite(Bike()) # Bike engine started ignite(Boat()) # Boat engine started
University Exam Tip
Duck typing differentiates Python from statically typed languages like Java/C++. In exams, emphasize that Python does not check types — it checks whether the object has the required method. This makes Python more flexible.
3. Operator Overloading
Python allows you to redefine the behavior of built-in operators for custom objects using dunder (double underscore) methods. This is a form of compile-time polymorphism.
class Point: def __init__(self, x, y): self.x = x self.y = y # Operator + overloading def __add__(self, other): return Point(self.x + other.x, self.y + other.y) # len() overloading def __len__(self): return int((self.x**2 + self.y**2)**0.5) # str() overloading def __str__(self): return f"({self.x}, {self.y})" p1 = Point(3, 4) p2 = Point(1, 2) print(p1 + p2) # (4, 6) print(len(p1)) # 5 print(str(p1)) # (3, 4)
len() — Polymorphic Function
The len() function works with strings, lists, tuples, dicts, and custom classes — each returning the appropriate length. This is built-in polymorphism.
print(len("Hello")) # 5 (string) print(len([1, 2, 3])) # 3 (list) print(len({"a": 1, "b": 2})) # 2 (dict) print(len((10, 20))) # 2 (tuple)
Common Dunder Methods for Operator Overloading
| Operator / Function | Dunder Method | Purpose |
|---|---|---|
| + (add) | __add__ | Addition of objects |
| - (sub) | __sub__ | Subtraction of objects |
| * (mul) | __mul__ | Multiplication of objects |
| len() | __len__ | Length of object |
| str() | __str__ | String representation |
| repr() | __repr__ | Developer string repr |
| == (eq) | __eq__ | Equality comparison |
| < (lt) | __lt__ | Less-than comparison |
4. Function Overloading (Using Default Arguments)
Python does not support traditional function overloading (same function name with different parameter types). Instead, we simulate it using default arguments or *args/**kwargs.
def add(a, b=0, c=0): return a + b + c print(add(5)) # 5 print(add(5, 3)) # 8 print(add(5, 3, 2)) # 10 # Using *args for variable arguments def multiply(*args): result = 1 for num in args: result *= num return result print(multiply(2, 3)) # 6 print(multiply(2, 3, 4)) # 24
Practical Example: Polymorphism with Shapes
class Circle: def __init__(self, radius): self.radius = radius def area(self): return 3.14 * self.radius ** 2 def __str__(self): return f"Circle(r={self.radius})" class Rectangle: def __init__(self, l, w): self.l = l self.w = w def area(self): return self.l * self.w def __str__(self): return f"Rectangle({self.l}x{self.w})" class Triangle: def __init__(self, base, height): self.base = base self.height = height def area(self): return 0.5 * self.base * self.height def __str__(self): return f"Triangle(b={self.base},h={self.height})" # Polymorphism: same function, different objects shapes = [Circle(5), Rectangle(4, 6), Triangle(3, 8)] for shape in shapes: print(f"{shape} → Area = {shape.area()}") # Output: # Circle(r=5) → Area = 78.5 # Rectangle(4x6) → Area = 24 # Triangle(b=3,h=8) → Area = 12.0
Common Mistakes
- Trying to overload a function by defining it twice — Python uses the last definition only.
- Confusing polymorphism with overloading — polymorphism is about one interface, many forms.
- Forgetting
selfparameter when overriding methods. - Assuming Python checks object types — it does not (duck typing).
Key Points
Polymorphism means "many forms" — one interface, multiple implementations.
Method overriding is the primary form of runtime polymorphism in Python.
Duck typing allows objects of unrelated classes to be used interchangeably.
Operator overloading uses dunder methods like __add__, __len__, __str__.
Python does not support traditional function overloading — use default args or *args.
Built-in functions like len(), str(), print() are themselves polymorphic.
Practice Questions
- Write a program using method overriding where a parent class
Vehiclehas astart()method and child classes override it. - Explain duck typing with a code example involving two unrelated classes.
- Overload the
+operator in a classMatrixto add two 2×2 matrices. - Difference between polymorphism and inheritance.
- How does
len()demonstrate polymorphism? Give 3 examples.
Summary
Polymorphism is a powerful OOP feature that makes code flexible and extensible. Python achieves it through method overriding, duck typing, and operator overloading. Understanding polymorphism is essential for writing clean, reusable code and for answering university exam questions on OOP.