Method Overriding
A subclass can override a parent method to change its behaviour.
class Animal:
def speak(self):
return "..."
class Dog(Animal):
def speak(self): # Override
return "Woof!"
class Cat(Animal):
def speak(self): # Override
return "Meow!"
class Duck(Animal):
def speak(self):
return "Quack!"
animals = [Dog(), Cat(), Duck()]
for animal in animals:
print(animal.speak()) # Each responds differentlyDuck Typing
"If it walks like a duck and quacks like a duck, it's a duck." Python doesn't require inheritance — any object with the right method works.
class Dog:
def speak(self): return "Woof!"
class Robot:
def speak(self): return "Beep boop!"
class Human:
def speak(self): return "Hello!"
# No shared base class needed!
entities = [Dog(), Robot(), Human()]
for e in entities:
print(e.speak())Polymorphism with Abstract Methods
Use ABC to enforce that subclasses implement required methods.
from abc import ABC, abstractmethod
import math
class Shape(ABC):
@abstractmethod
def area(self): ...
@abstractmethod
def perimeter(self): ...
class Circle(Shape):
def __init__(self, r): self.r = r
def area(self): return math.pi * self.r**2
def perimeter(self): return 2 * math.pi * self.r
class Square(Shape):
def __init__(self, s): self.s = s
def area(self): return self.s**2
def perimeter(self): return 4 * self.s
for shape in [Circle(5), Square(4)]:
print(f"Area: {shape.area():.2f}, Perimeter: {shape.perimeter():.2f}")Operator Overloading
Define special methods to make operators work with your classes.
class Vector:
def __init__(self, x, y):
self.x, self.y = x, y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __mul__(self, scalar):
return Vector(self.x * scalar, self.y * scalar)
def __str__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2) # Vector(4, 6)
print(v1 * 3) # Vector(3, 6)Duck Typing: Python's Polymorphism Without Inheritance
In many languages polymorphism requires a shared base class. Python uses duck typing: "if it walks like a duck and quacks like a duck, it's a duck." Any object with the right method works — no common ancestor needed.
class Dog: quack = None
class Duck:
def speak(self): return "Quack"
class Cat:
def speak(self): return "Meow"
for animal in (Duck(), Cat()):
print(animal.speak()) # works on both — no shared base class
Operator polymorphism via magic methods
The same + means different things by type — that's polymorphism too. Your classes join in by defining __add__, __len__, __str__:
print(3 + 4) # 7 (integer add)
print("a" + "b") # ab (string concat)
print([1] + [2]) # [1, 2] (list extend)
EAFP style: prefer try: obj.speak() over if isinstance(obj, Duck). Checking behavior beats checking type — it keeps your code open to new classes you haven't met yet.
🏋️ Practical Exercise
Model animals with shared behavior:
- Create a base class
Animalwith aspeak()method. - Create
Dog,Cat, andCowsubclasses that overridespeak(). - Put several animals in a list and call
speak()on each in one loop. - Observe how the same call produces different behavior per type.
🔥 Challenge Exercise
Write a function total_area(shapes) that accepts any iterable of objects exposing an area() method (Circle, Square, Triangle, …) and returns their combined area — relying on duck typing rather than a shared base class. Then add a Square class that overloads the + operator to combine two squares into one with the summed area, demonstrating operator-level polymorphism.
📋 Summary
- Polymorphism lets a single interface work with objects of different types.
- Method overriding replaces a parent method in a subclass so the same call behaves differently per type.
- Duck typing means Python cares about whether an object has the needed method, not its class — “if it walks like a duck…”.
- Python does not support traditional method overloading; use default or variable arguments instead.
- Operator overloading (via magic methods) is polymorphism at the operator level.
- Abstract base classes enforce a shared interface that polymorphic code can rely on.
Interview Questions on Polymorphism
- What is polymorphism in object-oriented programming?
- What is method overriding and how does it relate to polymorphism?
- What is duck typing in Python?
- Does Python support method overloading? Why or why not?
- How does operator overloading demonstrate polymorphism?
- What is the difference between overriding and overloading?
- How does polymorphism work together with abstract base classes?
Related Topics
FAQ
Overriding redefines an inherited method in a subclass (same name and signature). Overloading defines multiple versions of a method differing by arguments. Python supports overriding natively but not true overloading — default and *args arguments cover those cases.
A style where an object’s suitability is determined by the methods it has, not its type. If an object has an area() method, polymorphic code can use it regardless of which class it belongs to — “if it quacks like a duck, it’s a duck.”
No. Thanks to duck typing, unrelated classes that share a method name can be used interchangeably without a common base class. Inheritance and abstract base classes are one way to guarantee that shared interface, not a requirement.
Operators like + behave differently depending on operand type — integers add, strings concatenate, lists extend. By implementing magic methods you extend this polymorphic behavior to your own classes.

