Python Polymorphism
In this page:
class ParentClass:
def method_name(self):
# base version
class ChildClass(ParentClass):
def method_name(self):
# overridden version
What is Polymorphism?
Polymorphism means objects of different classes can respond to the exact same method call in their own way -- calling .speak() on a Dog and a Cat runs different code in each, but the calling code doesn't need to know or care which specific class it's dealing with.
Example: What is Polymorphism?
class Dog:
def speak(self):
print("Woof")
class Cat:
def speak(self):
print("Meow")
for animal in [Dog(), Cat()]:
animal.speak() # same call, different behavior depending on the actual object
Polymorphism with Inheritance
The most common form of polymorphism pairs naturally with inheritance: a base class defines a method, and each subclass overrides it with its own version, so a loop that calls animal.speak() on a mixed list of Dog and Cat objects gets the right sound for each without any if/else type checking.
Example: Polymorphism with Inheritance
class Animal:
def speak(self):
pass # placeholder, meant to be overridden
class Dog(Animal):
def speak(self):
print("Woof")
class Cat(Animal):
def speak(self):
print("Meow")
for animal in [Dog(), Cat()]:
animal.speak() # each subclass's own override runs
Duck Typing
Python doesn't require an object to belong to a specific class or inherit from a specific base to be used somewhere -- if it has the methods being called on it, that's enough.
This 'duck typing' means you can pass any object with a .read() method to code expecting a file, whether or not it's literally a file.
Example: Duck Typing
class Duck:
def read(self):
print("Duck pretending to read")
def process(obj):
obj.read() # works on any object that has a read() method
process(Duck())
Built-in Polymorphic Functions
Functions like len() and operators like + are polymorphic in the sense that they behave differently depending on the type they're given -- len() counts characters for a string but items for a list, and + concatenates strings but adds numbers, all through the same syntax.
Example: Built-in Polymorphic Functions
print(len("hello")) # len() counts characters for a string
print(len([1, 2, 3])) # len() counts items for a list
print("a" + "b") # + concatenates strings
print(1 + 2) # + adds numbers
Abstract Base Classes
An abstract base class defines method signatures that subclasses are required to implement, using the abc module -- this gives you compile-time-like safety that every subclass genuinely provides the methods your polymorphic code expects, rather than failing at runtime with an AttributeError.
Example: Abstract Base Classes
from abc import ABC, abstractmethod
class Shape(ABC): # abstract base class, can't be instantiated directly
@abstractmethod
def area(self): # subclasses are required to implement this
pass
class Square(Shape):
def __init__(self, side):
self.side = side
def area(self):
return self.side ** 2
print(Square(4).area())
- Checking types with
isinstancechains to choose behaviour, when giving each class a method of the same name lets polymorphism do the work. - Assuming the same method name means the same signature, so passing objects whose methods take different arguments fails with
TypeError. - Forgetting to implement a method the caller expects in one class, which raises
AttributeErroronly when that object is used.
Chapter Quiz — Complete all 11 topics to unlock
0/11 topics done
Complete these topics first: