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.

Try Python OOP Polymorphism Code

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.

polymorphism_demo.py
Try in Editor
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))
Terminal Output
Calculated Area: 16.00
Calculated Area: 28.27

Real-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.