← Back to Chapters

Python Polymorphism

? Python Polymorphism

? Quick Overview

Polymorphism means "many forms". In Python, it allows the same function name or operator to work in different ways depending on the context (the data type or the class that uses it).

This makes code more flexible, easier to extend, and more readable because you can use the same interface for different underlying implementations.

? Key Concepts

  • Same name, different behavior: Methods or functions share a common name but behave differently for different objects.
  • Built-in polymorphism: Python functions like len() work with strings, lists, dictionaries, and more.
  • Class polymorphism: Different classes can define the same method name (like sound()), but each provides its own implementation.
  • Polymorphism with inheritance: Child classes can override parent methods to change or specialize behavior.
  • Duck typing: If an object has the required method, it can be used, regardless of its actual type.

? Syntax and Theory

There is no special keyword for polymorphism in Python. It naturally appears in:

  • Functions that work with multiple data types.
  • Classes that share method names.
  • Inheritance hierarchies where child classes override parent methods.

As long as an object provides the expected method or operation, it can be used in a polymorphic way.

? Built-in Polymorphism

Functions like len() work on different data types in different ways.

? View Built-in Polymorphism Example
print(len("Hello"))              # 5 (string length)
print(len([1, 2, 3]))            # 3 (list length)
print(len({"a": 1, "b": 2}))     # 2 (dictionary keys count)

? Polymorphism in Classes

Different classes can have methods with the same name, but their behaviors can be different. You can then loop over a collection of objects and call the same method on each one.

? View Class Polymorphism Example
class Dog:
    def sound(self):
        return "Bark"  # Dog's sound implementation

class Cat:
    def sound(self):
        return "Meow"  # Cat's sound implementation

animals = [Dog(), Cat()]  # List of animal objects
for animal in animals:
    print(animal.sound())  # Polymorphic method call

⚙️ Polymorphism with Inheritance

Inheritance allows child classes to override parent methods, providing specific implementations.

? View Inheritance Polymorphism Example
class Bird:
    def fly(self):
        print("Most birds can fly")

class Penguin(Bird):
    def fly(self):
        print("Penguins cannot fly")

bird = Bird()
penguin = Penguin()

bird.fly()     # Most birds can fly
penguin.fly()  # Penguins cannot fly

? Live Output and Explanation

  • len("Hello")5 because the string has 5 characters.
  • len([1, 2, 3])3 because the list has 3 elements.
  • len({"a": 1, "b": 2})2 because the dictionary has 2 keys.
  • In the Dog / Cat example, both classes define sound(), so the loop can call animal.sound() without caring which class the object belongs to.
  • In the Bird / Penguin example, Penguin overrides fly() and changes the behavior while still using the same method name.

✅ Tips and Best Practices

  • Use polymorphism to make your code flexible and easier to extend.
  • Prefer common method names (e.g., sound(), draw(), move()) for consistency.
  • Design your functions and loops to depend on behavior (methods) rather than concrete types.
  • Polymorphism works naturally with duck typing in Python: "If it walks like a duck and quacks like a duck, it's a duck."

? Try It Yourself

  • Create Car and Bike classes, both with a move() method. Put their objects in a list and call move() in a loop.
  • Make a parent class and a child class. Override a method in the child class to change its behavior (similar to Bird and Penguin).
  • Test operator polymorphism with the + operator by adding:
    • Two numbers
    • Two strings
    • Two lists
    Observe how the same operator behaves differently based on operand types.