Python OOP Polymorphism: Duck Typing and Interfaces
Master polymorphism in Python. Learn how to write flexible, loosely coupled code using duck typing, method overriding, and abstract base classes.
Overview
Polymorphism is a Greek term meaning "many forms". In Object-Oriented Programming, it refers to the ability of different classes to respond to the same method call in their own unique way. Polymorphism allows you to write a single function that can process many different types of objects, provided they share a common interface. This enables low coupling and makes your software systems highly adaptable and easy to extend.
In Python, polymorphism is deeply tied to a concept known as Duck Typing. The term comes from the phrase: "If it walks like a duck and it quacks like a duck, then it must be a duck." In dynamically typed Python, a function does not care what class an object belongs to; it only cares whether that object implements the requested methods. For instance, if you have a function that calls `.speak()`, you can pass it a Dog, a Cat, or a Robot—as long as they all have a `.speak()` method, the code runs perfectly.
For stricter architectures, Python provides Abstract Base Classes (ABCs) via the built-in `abc` module. By inheriting from `abc.ABC` and using the `@abstractmethod` decorator, you can define formal interfaces that child classes are forced to implement. If a child class fails to define the abstract methods, Python will raise a TypeError when you try to instantiate it. Balancing flexible duck typing with formal abstract classes is a key skill for designing resilient Python libraries.
Code Example
Implementing polymorphic classes representing shapes that compute their area.
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
"""Must be implemented by subclasses."""
pass
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side * self.side
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
import math
return math.pi * (self.radius ** 2)
# Polymorphic function accepting any Shape
def print_area(shape: Shape):
print(f"Calculated Area: {shape.area():.2f}")
print_area(Square(4))
print_area(Circle(3))Calculated Area: 16.00
Calculated Area: 28.27Real-world Use Cases
- Writing payment processors that handle CreditCard, PayPal, and Stripe objects
- Drawing various elements (Text, Image) using a unified render loop
- Mocking external API connections during unit testing
Frequently Asked Questions
What is Duck Typing?
It is Python's dynamic approach to polymorphism. It checks for the presence of methods and properties at runtime rather than verifying inheritance from a specific parent class.
Can you instantiate an Abstract Base Class?
No. Attempting to instantiate a class that inherits from ABC and contains abstract methods will raise a TypeError.
Keep Learning
Recommended Python Resources
Expand your knowledge with related interactive tutorials, cheat sheets, and code comparisons.
How to Sort a List in Python
Learn how to sort a list in Python using the sort() method and the sorted() function. Discover custom key sorting and reverse order examples.
Python String Methods
A complete reference guide for Python string manipulation. Master formatting, searching, splitting, replacing, and checking string properties.
Python vs JavaScript: Which Programming Language is Best?
A comprehensive comparison between Python and JavaScript. Explore syntax differences, performance, use cases (backend vs frontend), and coding examples.