Learn polymorphism in Python OOP with practical examples. Understand method overriding, duck typing, and operator overloading for flexible and reusable code.
Polymorphism is a core concept in object-oriented programming (OOP) that allows objects of different classes to be treated as objects of a common superclass. The word “polymorphism” comes from Greek meaning “many forms”.
Polymorphism lets you:
Method Overriding: When a child class provides a different implementation of a method that is already defined in its parent class.
Method Overloading: Python doesn’t support this directly like Java/C++, but we can achieve similar functionality using default arguments or variable-length arguments.
Duck Typing: “If it walks like a duck and quacks like a duck, it must be a duck” - we don’t check types, just behavior.
class Animal:
def speak(self):
print("Animal speaks")
class Dog(Animal):
def speak(self): # Overriding the speak method
print("Dog barks")
class Cat(Animal):
def speak(self): # Overriding the speak method
print("Cat meows")
# Polymorphic behavior
animals = [Animal(), Dog(), Cat()]
for animal in animals:
animal.speak()
Output:
Animal speaks
Dog barks
Cat meows
class Parrot:
def fly(self):
print("Parrot can fly")
def swim(self):
print("Parrot can't swim")
class Penguin:
def fly(self):
print("Penguin can't fly")
def swim(self):
print("Penguin can swim")
# Common interface
def flying_test(bird):
bird.fly()
# Instantiate objects
parrot = Parrot()
penguin = Penguin()
# Polymorphic behavior
flying_test(parrot)
flying_test(penguin)
Output:
Parrot can fly
Penguin can't fly
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
# Overloading the + operator
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __str__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(2, 3)
v2 = Vector(1, 2)
print(v1 + v2) # Uses the overloaded + operator
Output:
Vector(3, 5)
class Payment:
def process_payment(self, amount):
pass
class CreditCardPayment(Payment):
def process_payment(self, amount):
print(f"Processing credit card payment of ${amount}")
class PayPalPayment(Payment):
def process_payment(self, amount):
print(f"Processing PayPal payment of ${amount}")
class BankTransferPayment(Payment):
def process_payment(self, amount):
print(f"Processing bank transfer of ${amount}")
def checkout(payment_method, amount):
payment_method.process_payment(amount)
# Usage
credit_card = CreditCardPayment()
paypal = PayPalPayment()
bank_transfer = BankTransferPayment()
checkout(credit_card, 100) # Processing credit card payment of $100
checkout(paypal, 50) # Processing PayPal payment of $50
checkout(bank_transfer, 200) # Processing bank transfer of $200
In this example, the checkout
function doesn’t need to know what specific type of payment method it’s using - it just calls process_payment()
. Each payment type implements this method differently, demonstrating polymorphism.
Polymorphism is a powerful concept that helps make your Python code more flexible and easier to work with as your programs grow in complexity.
Objective: Create classes with method overriding.
Problem:
Animal
with a make_sound()
method that prints “Generic animal sound”.Dog
, Cat
, Cow
) that override make_sound()
with their own sounds.make_sound()
for each.Example Output:
Generic animal sound
Woof!
Meow!
Moo!
Objective: Use polymorphism to calculate areas.
Problem:
Shape
with an abstract area()
method (use pass
).Circle
, Square
, and Triangle
that implement area()
.Requirements:
Circle
: Initialize with radius, area = πr²Square
: Initialize with side length, area = side²Triangle
: Initialize with base/height, area = 0.5 * base * heightObjective: Practice “duck typing” with unrelated classes.
Problem:
Car
and Bird
.move()
method but with different implementations:
Car.move()
prints “Car is driving”Bird.move()
prints “Bird is flying”travel(object)
that calls object.move()
.travel()
.Objective: Overload operators for a custom class.
Problem:
Book
class with attributes title
and pages
.+
operator to combine two books into a new “collection” book:
book1 = Book("Python Basics", 100)
book2 = Book("OOP Guide", 150)
book3 = book1 + book2
print(book3.title) # "Collection: Python Basics & OOP Guide"
print(book3.pages) # 250
Objective: Simulate a real-world polymorphic system.
Problem:
MediaPlayer
with a play()
method.MP3Player
, VideoPlayer
, StreamingPlayer
.play()
with specific behavior:
MP3Player
: “Playing audio track…”VideoPlayer
: “Playing video…”StreamingPlayer
: “Streaming from cloud…”play()
for each.Objective: Polymorphism in financial calculations.
Problem:
BankAccount
with a calculate_interest()
method.SavingsAccount
(5% interest) and FixedDeposit
(7% interest).Example:
savings = SavingsAccount(1000)
fixed = FixedDeposit(1000)
print(savings.calculate_interest()) # 50.0
print(fixed.calculate_interest()) # 70.0
Objective: Use polymorphism with numbers.
Problem:
double(x)
that returns x * 2
.print(double(5)) # 10
print(double(3.14)) # 6.28
print(double([1,2])) # [1,2,1,2]
print(double("Hi")) # "HiHi"
Objective: Polymorphic behavior in a game.
Problem:
GameCharacter
with an attack()
method.Warrior
, Mage
, and Archer
with unique attack messages:
attack()
for each.Objective: Polymorphic file operations.
Problem:
TextFile
and CSVFile
, both with a read()
method.TextFile.read()
returns the text file’s content as a string.CSVFile.read()
returns the data as a list of lists.process_file(file)
that calls read()
on any file type.Objective: Design a flexible logging system.
Problem:
Logger
with a log(message)
method.ConsoleLogger
, FileLogger
, and DatabaseLogger
.super()
, and multilevel inheritance.