Ojasa Mirai

Ojasa Mirai

Python

Loading...

Learning Level

🟢 Beginner🔵 Advanced
Classes & ObjectsMethods & SelfInstance VariablesClass VariablesConstructors & InitializationInheritance BasicsPolymorphismEncapsulationMagic Methods & Dunder
Python/Oop/Polymorphism

🔀 Polymorphism — Many Forms, One Interface

Polymorphism means "many forms." It allows you to write code that works with objects of different types through a common interface. Polymorphism makes your code flexible and extensible—you can add new types without changing existing code.


🎯 What is Polymorphism?

Polymorphism allows different objects to respond to the same method call in their own way. You can write code that treats multiple different types uniformly, and each object responds according to its own implementation.

class Dog:
    def speak(self):
        return "Woof!"

class Cat:
    def speak(self):
        return "Meow!"

class Bird:
    def speak(self):
        return "Tweet!"

# Polymorphism in action - same method, different behavior
animals = [Dog(), Cat(), Bird()]

for animal in animals:
    print(animal.speak())  # Each responds differently
    # Output:
    # Woof!
    # Meow!
    # Tweet!

🔄 Method Overriding for Polymorphism

The most common way to achieve polymorphism is through method overriding. Different child classes override the same method with different implementations.

class Shape:
    def area(self):
        pass  # Base implementation

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius

    def area(self):
        return 3.14 * self.radius ** 2

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height

    def area(self):
        return self.width * self.height

class Triangle(Shape):
    def __init__(self, base, height):
        self.base = base
        self.height = height

    def area(self):
        return 0.5 * self.base * self.height

# Polymorphic function
def print_area(shape):
    print(f"Area: {shape.area()}")

# Works with any shape
shapes = [Circle(5), Rectangle(4, 6), Triangle(3, 4)]
for shape in shapes:
    print_area(shape)
    # Output:
    # Area: 78.5
    # Area: 24
    # Area: 6.0

🎯 Polymorphic Functions

Write functions that accept any object with the required methods. The function doesn't need to know the exact type—it just calls the method and the object responds appropriately.

class Guitar:
    def play(self):
        return "Strumming a guitar... Twang!"

class Piano:
    def play(self):
        return "Playing piano... Plink plink!"

class Violin:
    def play(self):
        return "Playing violin... Screech!"

# Function works with any object that has a play() method
def perform_concert(musicians):
    for musician in musicians:
        print(musician.play())

# Create different instruments
band = [Guitar(), Piano(), Violin(), Guitar()]

perform_concert(band)
# Output:
# Strumming a guitar... Twang!
# Playing piano... Plink plink!
# Playing violin... Screech!
# Strumming a guitar... Twang!

🦆 Duck Typing

Python uses "duck typing"—if an object has the required methods, it can be used. You don't need to formally declare that a class inherits from another. This makes Python very flexible.

class Printer:
    def print_document(self, document):
        return f"Printing: {document}"

class DigitalDisplay:
    def print_document(self, document):
        return f"Displaying: {document}"

class Speaker:
    def print_document(self, document):
        return f"Speaking: {document}"

# Function doesn't care about class hierarchy
def handle_document(device, doc):
    return device.print_document(doc)

# Works with any object that has print_document method
printer = Printer()
display = DigitalDisplay()
speaker = Speaker()

print(handle_document(printer, "Letter"))
print(handle_document(display, "Slide"))
print(handle_document(speaker, "Instructions"))

📋 List of Different Types

Polymorphism shines when working with lists of different object types. Process them all uniformly.

class Employee:
    def work(self):
        pass

    def get_salary(self):
        pass

class Manager(Employee):
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary

    def work(self):
        return f"{self.name} manages the team"

    def get_salary(self):
        return self.salary

class Developer(Employee):
    def __init__(self, name, salary, language):
        self.name = name
        self.salary = salary
        self.language = language

    def work(self):
        return f"{self.name} codes in {self.language}"

    def get_salary(self):
        return self.salary

class Intern(Employee):
    def __init__(self, name, salary):
        self.name = name
        self.salary = salary

    def work(self):
        return f"{self.name} learns and assists"

    def get_salary(self):
        return self.salary

# Process all employees uniformly
employees = [
    Manager("Alice", 100000),
    Developer("Bob", 80000, "Python"),
    Developer("Charlie", 75000, "JavaScript"),
    Intern("Diana", 30000)
]

total_payroll = 0
for emp in employees:
    print(emp.work())
    total_payroll += emp.get_salary()

print(f"\nTotal payroll: ${total_payroll}")

📚 Real-World Examples

Payment Systems

class PaymentMethod:
    def process_payment(self, amount):
        pass

class CreditCard(PaymentMethod):
    def __init__(self, card_number):
        self.card_number = card_number

    def process_payment(self, amount):
        return f"Processing ${amount} with credit card {self.card_number[-4:]}"

class PayPal(PaymentMethod):
    def __init__(self, email):
        self.email = email

    def process_payment(self, amount):
        return f"Processing ${amount} via PayPal ({self.email})"

class Bitcoin(PaymentMethod):
    def __init__(self, wallet):
        self.wallet = wallet

    def process_payment(self, amount):
        return f"Processing ${amount} in Bitcoin to {self.wallet}"

class CheckoutSystem:
    def __init__(self, payment_method):
        self.payment_method = payment_method

    def checkout(self, amount):
        return self.payment_method.process_payment(amount)

# Use any payment method
card = CreditCard("4532-1234-5678-9010")
paypal = PayPal("user@example.com")
bitcoin = Bitcoin("1A1z7agoat4...")

checkout1 = CheckoutSystem(card)
print(checkout1.checkout(99.99))

checkout2 = CheckoutSystem(paypal)
print(checkout2.checkout(99.99))

checkout3 = CheckoutSystem(bitcoin)
print(checkout3.checkout(99.99))

Vehicle Rental System

class Vehicle:
    def __init__(self, make, model, daily_rate):
        self.make = make
        self.model = model
        self.daily_rate = daily_rate

    def calculate_rental_cost(self, days):
        pass

    def get_info(self):
        pass

class Car(Vehicle):
    def calculate_rental_cost(self, days):
        return self.daily_rate * days

    def get_info(self):
        return f"Car: {self.make} {self.model}"

class Truck(Vehicle):
    def __init__(self, make, model, daily_rate, tonnage):
        super().__init__(make, model, daily_rate)
        self.tonnage = tonnage

    def calculate_rental_cost(self, days):
        return self.daily_rate * days * 1.5  # 50% more for trucks

    def get_info(self):
        return f"Truck: {self.make} {self.model} ({self.tonnage} ton)"

class Motorcycle(Vehicle):
    def calculate_rental_cost(self, days):
        return self.daily_rate * days * 0.6  # 40% less for bikes

    def get_info(self):
        return f"Motorcycle: {self.make} {self.model}"

# Rental fleet with different vehicles
fleet = [
    Car("Toyota", "Camry", 50),
    Truck("Ford", "F-150", 75, 2),
    Motorcycle("Harley", "Davidson", 40),
    Car("Honda", "Civic", 45)
]

rental_days = 3
total_revenue = 0

for vehicle in fleet:
    cost = vehicle.calculate_rental_cost(rental_days)
    total_revenue += cost
    print(f"{vehicle.get_info()} - {rental_days} days: ${cost}")

print(f"\nTotal revenue: ${total_revenue}")

✅ Key Takeaways

ConceptRemember
PolymorphismObjects of different types respond to same method differently
Method OverridingChild classes provide their own implementation of parent methods
Common InterfaceDifferent types expose the same method names
FlexibilityWrite code once that works with multiple types
Duck TypingIf it walks and quacks like a duck, use it as a duck
ExtensibilityAdd new types without changing existing code
Type IndependenceCode doesn't need to know exact object type

🔗 What's Next?

Now let's learn about encapsulation, which helps you control how data is accessed and modified.

Next: Encapsulation →


Ready to practice? Try challenges or explore more concepts


Resources

Python Docs

Ojasa Mirai

Master AI-powered development skills through structured learning, real projects, and verified credentials. Whether you're upskilling your team or launching your career, we deliver the skills companies actually need.

Learn Deep • Build Real • Verify Skills • Launch Forward

Courses

PythonFastapiReactJSCloud

© 2026 Ojasa Mirai. All rights reserved.

TwitterGitHubLinkedIn