Bird
Raised Fist0
Pythonprogramming~15 mins

Polymorphism through inheritance in Python - Deep Dive

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Overview - Polymorphism through inheritance
What is it?
Polymorphism through inheritance means that different classes can share the same method name but behave differently. It allows objects of different types to be treated as objects of a common parent class. This lets us write flexible code that works with many kinds of objects without knowing their exact type.
Why it matters
Without polymorphism, programmers would need to write separate code for every object type, making programs long and hard to maintain. Polymorphism lets us write simpler, reusable code that can handle new object types easily. This saves time and reduces bugs in real projects.
Where it fits
Before learning this, you should understand classes and inheritance basics in Python. After this, you can explore interfaces, abstract classes, and design patterns that use polymorphism for more complex software design.
Mental Model
Core Idea
Polymorphism through inheritance means one method name can do different things depending on the object's class.
Think of it like...
Imagine a universal remote control that can operate different devices like TV, DVD player, or sound system. Pressing the 'power' button turns on the device, but what actually happens depends on which device the remote is controlling.
┌───────────────┐
│   Animal      │
│  (parent)     │
│  speak()      │
└──────┬────────┘
       │
 ┌─────┴─────┐    ┌───────────┐
 │ Dog       │    │ Cat       │
 │ speak()   │    │ speak()   │
 └───────────┘    └───────────┘

Calling speak() on Dog says 'Woof', on Cat says 'Meow'.
Build-Up - 7 Steps
1
FoundationUnderstanding classes and methods
🤔
Concept: Learn what classes and methods are in Python.
A class is like a blueprint for creating objects. Methods are functions inside classes that describe what objects can do. Example: class Animal: def speak(self): print('Animal sound') animal = Animal() animal.speak() # prints 'Animal sound'
Result
You can create objects and call their methods to perform actions.
Understanding classes and methods is essential because polymorphism works by overriding these methods in child classes.
2
FoundationBasics of inheritance in Python
🤔
Concept: Learn how one class can inherit from another to reuse code.
Inheritance lets a new class (child) use code from an existing class (parent). Example: class Animal: def speak(self): print('Animal sound') class Dog(Animal): pass dog = Dog() dog.speak() # prints 'Animal sound' because Dog inherits speak()
Result
Child classes get methods from parent classes automatically.
Inheritance allows code reuse and sets the stage for polymorphism by sharing method names.
3
IntermediateOverriding methods in child classes
🤔Before reading on: do you think a child class can change how a method from the parent works? Commit to yes or no.
Concept: Child classes can provide their own version of a method, replacing the parent's version.
You can define a method in a child class with the same name as in the parent. This is called overriding. Example: class Dog(Animal): def speak(self): print('Woof') class Cat(Animal): def speak(self): print('Meow') Dog().speak() # prints 'Woof' Cat().speak() # prints 'Meow'
Result
Calling speak() on different child objects produces different outputs.
Overriding lets child classes customize behavior while keeping the same method name, enabling polymorphism.
4
IntermediateUsing parent references for polymorphism
🤔Before reading on: If you have a list of Animal objects, do you think calling speak() on each will use the child class's method or the parent's? Commit to your answer.
Concept: You can treat different child objects as their parent type and still get their unique behavior when calling overridden methods.
Example: animals = [Dog(), Cat(), Animal()] for animal in animals: animal.speak() Output: Woof Meow Animal sound Even though the list is typed as Animal, the correct speak() runs for each object.
Result
Code can work with general types but still use specific behaviors of child classes.
This shows polymorphism: one interface (speak) with many implementations depending on the object.
5
IntermediatePolymorphism with method parameters
🤔Before reading on: Can a function accept a parent class object and still work correctly with any child class object? Commit to yes or no.
Concept: Functions can accept parent class objects and automatically support any child class objects thanks to polymorphism.
Example: def make_it_speak(animal: Animal): animal.speak() make_it_speak(Dog()) # Woof make_it_speak(Cat()) # Meow make_it_speak(Animal()) # Animal sound The function works with any subclass of Animal.
Result
Functions become more flexible and reusable with polymorphism.
Polymorphism lets you write code that works with many types without changing the code.
6
AdvancedUsing super() to extend parent methods
🤔Before reading on: When overriding a method, do you think you can still call the parent's version inside the child? Commit to yes or no.
Concept: The super() function lets child methods call the parent's method to reuse or extend behavior.
Example: class Bird(Animal): def speak(self): super().speak() # call parent method print('Tweet') Bird().speak() Output: Animal sound Tweet This shows how to add to the parent's behavior instead of replacing it.
Result
You can combine parent and child behaviors cleanly.
Knowing super() helps avoid code duplication and supports complex polymorphic behaviors.
7
ExpertPolymorphism internals and method resolution
🤔Before reading on: Do you think Python decides which method to call at compile time or runtime? Commit to your answer.
Concept: Python uses a method resolution order (MRO) at runtime to find the correct method to call based on the object's class hierarchy.
When you call a method, Python looks up the method in the object's class, then its parents, following the MRO. Example: class A: def speak(self): print('A') class B(A): def speak(self): print('B') class C(B): pass C().speak() # prints 'B' Python finds speak() in B before A. This dynamic lookup is why polymorphism works.
Result
Method calls adapt to the actual object's class at runtime, enabling flexible behavior.
Understanding MRO and runtime lookup explains why polymorphism is powerful and how multiple inheritance affects it.
Under the Hood
Polymorphism through inheritance works because Python stores the class of each object and uses it at runtime to find methods. When you call a method, Python checks the object's class dictionary for the method. If not found, it checks parent classes following the method resolution order (MRO). This dynamic lookup means the same method name can run different code depending on the object's actual class.
Why designed this way?
This design allows flexibility and extensibility. Early programming languages used static method binding, which limited reuse. Python's dynamic method lookup supports open-ended designs where new classes can override behavior without changing existing code. It also supports multiple inheritance with a clear MRO to avoid ambiguity.
Object instance
    │
    ▼
┌─────────────┐
│  Class C    │
│  methods:   │
│  speak()    │
└─────┬───────┘
      │
      ▼
┌─────────────┐
│  Class B    │
│  methods:   │
│  speak()    │
└─────┬───────┘
      │
      ▼
┌─────────────┐
│  Class A    │
│  methods:   │
│  speak()    │
└─────────────┘

Method call: object.speak() → look in C, then B, then A
Myth Busters - 4 Common Misconceptions
Quick: Does polymorphism mean the parent class method always runs when called on a child object? Commit yes or no.
Common Belief:Polymorphism means the parent class method always runs, even if the child has its own method.
Tap to reveal reality
Reality:The child's overridden method runs instead of the parent's when called on a child object.
Why it matters:If you expect the parent method to run, your program may behave incorrectly or miss child-specific behavior.
Quick: Do you think polymorphism requires explicit interface declarations in Python? Commit yes or no.
Common Belief:Polymorphism requires declaring interfaces or abstract base classes explicitly.
Tap to reveal reality
Reality:Python supports polymorphism simply by method names and inheritance, without explicit interfaces.
Why it matters:Thinking interfaces are required can make learners overcomplicate simple polymorphic designs.
Quick: Can polymorphism only happen with inheritance? Commit yes or no.
Common Belief:Polymorphism only works through inheritance hierarchies.
Tap to reveal reality
Reality:Python also supports duck typing polymorphism without inheritance, based on method presence.
Why it matters:Limiting polymorphism to inheritance misses Python's flexible dynamic typing power.
Quick: Does Python decide which method to call when you write the code (compile time)? Commit yes or no.
Common Belief:Python decides method calls at compile time, so method calls are fixed.
Tap to reveal reality
Reality:Python decides method calls at runtime based on the object's actual class.
Why it matters:Misunderstanding this can lead to confusion about how dynamic behavior and method overriding work.
Expert Zone
1
Overriding methods can call super() to combine parent and child behaviors, which is crucial in complex inheritance trees.
2
Multiple inheritance uses a specific method resolution order (MRO) that can surprise even experienced developers if not understood.
3
Polymorphism can be combined with duck typing to write very flexible code that doesn't require inheritance at all.
When NOT to use
Avoid relying on polymorphism when performance is critical and dynamic dispatch overhead matters; use static typing or specialized functions instead. Also, if your classes have very different interfaces, polymorphism through inheritance may not fit; consider composition or protocols.
Production Patterns
In real systems, polymorphism is used to write generic code like GUI event handlers, database models, or payment processors. Frameworks rely on polymorphism to allow plugins or extensions. Polymorphism also enables design patterns like Strategy and Template Method.
Connections
Interfaces and Abstract Base Classes
Builds-on
Understanding polymorphism through inheritance prepares you to use interfaces and abstract classes, which formalize polymorphic contracts in larger systems.
Duck Typing
Alternative approach
Knowing polymorphism through inheritance helps contrast it with duck typing, where behavior depends on method presence rather than class hierarchy.
Biology - Species Classification
Analogous hierarchical structure
Just like animals are classified in a hierarchy with shared traits and specific differences, polymorphism uses class hierarchies to share and customize behavior.
Common Pitfalls
#1Overriding a method but forgetting to match the parent's method signature.
Wrong approach:class Dog(Animal): def speak(self, volume): # extra parameter print('Woof')
Correct approach:class Dog(Animal): def speak(self): print('Woof')
Root cause:Mismatch in method parameters breaks polymorphism because calls expecting the parent's signature fail.
#2Calling a method on a parent class instead of the child instance.
Wrong approach:animal = Animal() animal.speak() # prints 'Animal sound' even if you wanted Dog behavior
Correct approach:animal = Dog() animal.speak() # prints 'Woof' as expected
Root cause:Creating the wrong object type means polymorphism does not happen as expected.
#3Using inheritance just to share code without considering if classes really share behavior.
Wrong approach:class Car(Animal): pass # Car is not an Animal but inherits anyway
Correct approach:class Vehicle: pass class Car(Vehicle): pass
Root cause:Misusing inheritance breaks logical design and confuses polymorphism.
Key Takeaways
Polymorphism through inheritance lets one method name work differently depending on the object's class.
Child classes override parent methods to customize behavior while sharing a common interface.
Python decides which method to call at runtime using the object's class and method resolution order.
This feature enables flexible, reusable code that can handle many object types uniformly.
Understanding polymorphism is key to writing clean, maintainable, and extensible object-oriented programs.

Practice

(1/5)
1. What does polymorphism through inheritance allow in Python?
easy
A. One method name to have different behaviors in child classes
B. Multiple inheritance from unrelated classes
C. Using the same variable name in different functions
D. Creating objects without defining classes

Solution

  1. Step 1: Understand polymorphism concept

    Polymorphism means one method name can behave differently depending on the class.
  2. Step 2: Relate to inheritance

    Child classes override the method to provide their own behavior.
  3. Final Answer:

    One method name to have different behaviors in child classes -> Option A
  4. Quick Check:

    Polymorphism = One method, many behaviors [OK]
Hint: Polymorphism means same method, different actions [OK]
Common Mistakes:
  • Confusing polymorphism with multiple inheritance
  • Thinking polymorphism means same variable names
  • Believing objects can exist without classes
2. Which of the following is the correct way to override a method in a child class?
easy
A. Call the parent method inside the child method without redefining
B. Use the keyword override before the method
C. Define a method with the same name in the child class
D. Rename the method in the child class

Solution

  1. Step 1: Check method overriding syntax

    In Python, overriding means defining a method with the same name in the child class.
  2. Step 2: Verify other options

    Python does not use override keyword; renaming is not overriding; calling parent method alone is not overriding.
  3. Final Answer:

    Define a method with the same name in the child class -> Option C
  4. Quick Check:

    Override = same method name in child [OK]
Hint: Override by redefining method name in child class [OK]
Common Mistakes:
  • Using a non-existent override keyword
  • Thinking calling parent method equals overriding
  • Renaming method instead of overriding
3. What will be the output of this code?
class Animal:
    def sound(self):
        return "Some sound"

class Dog(Animal):
    def sound(self):
        return "Bark"

class Cat(Animal):
    def sound(self):
        return "Meow"

animals = [Dog(), Cat(), Animal()]
for a in animals:
    print(a.sound())
medium
A. Bark\nMeow\nSome sound
B. Some sound\nSome sound\nSome sound
C. Bark\nMeow\nError
D. Error\nError\nError

Solution

  1. Step 1: Identify method overriding

    Dog and Cat classes override sound method to return "Bark" and "Meow" respectively.
  2. Step 2: Trace the loop output

    Loop calls sound() on Dog(), Cat(), and Animal() objects, printing "Bark", "Meow", and "Some sound".
  3. Final Answer:

    Bark Meow Some sound -> Option A
  4. Quick Check:

    Overridden methods print their own sounds [OK]
Hint: Child method overrides parent, prints child's return [OK]
Common Mistakes:
  • Assuming parent method always runs
  • Expecting errors from calling base class method
  • Mixing output order
4. Find the error in this code that tries to demonstrate polymorphism:
class Vehicle:
    def move(self):
        print("Moving")

class Car(Vehicle):
    def move(self):
        print("Driving")

class Bike(Vehicle):
    def move(self):
        print("Riding")

vehicles = [Car(), Bike()]
for v in vehicles:
    v.move
medium
A. List should include Vehicle() instance
B. Incorrect class inheritance syntax
C. Using print instead of return in methods
D. Missing parentheses when calling move method

Solution

  1. Step 1: Check method calls in loop

    The code uses v.move without parentheses, so method is not called.
  2. Step 2: Understand effect of missing parentheses

    Without parentheses, method object is referenced but not executed, so no output occurs.
  3. Final Answer:

    Missing parentheses when calling move method -> Option D
  4. Quick Check:

    Method call needs () to execute [OK]
Hint: Always add () to call methods [OK]
Common Mistakes:
  • Forgetting parentheses on method calls
  • Thinking print vs return causes error here
  • Believing inheritance syntax is wrong
5. You want to add a new class Bird that also uses polymorphism with sound(). Which code correctly extends the existing classes and uses polymorphism?
hard
A. class Bird: def sound(self): return "Chirp" animals.append(Bird()) for a in animals: print(a.sound())
B. class Bird(Animal): def sound(self): return "Chirp" animals.append(Bird()) for a in animals: print(a.sound())
C. class Bird(Animal): def noise(self): return "Chirp" animals.append(Bird()) for a in animals: print(a.sound())
D. class Bird(Animal): def sound(self): print("Chirp") animals.append(Bird()) for a in animals: print(a.sound())

Solution

  1. Step 1: Check inheritance and method name

    Bird must inherit from Animal and override sound() method to maintain polymorphism.
  2. Step 2: Verify method behavior and usage

    Method returns string "Chirp" like others; appending Bird() to animals list and calling sound() works correctly.
  3. Final Answer:

    Correctly inherits Animal and overrides sound() returning "Chirp" -> Option B
  4. Quick Check:

    Polymorphism needs same method name and inheritance [OK]
Hint: Inherit and override same method name with matching signature [OK]
Common Mistakes:
  • Not inheriting from Animal class
  • Using different method name like noise()
  • Printing inside method instead of returning