intermediate

Inheritance & Polymorphism

7 min readLast updated: 2026-07-12

Overview

Inheritance lets new classes reuse code from existing classes, and polymorphism lets different classes share interfaces.

Learning Objectives

  • Create child classes that inherit from parent classes.
  • Override parent methods and use super() to run constructor logic.
  • Understand multiple inheritance hierarchies.

Concept Explanation

Inheritance defines parent-child relationships. A subclass inherits attributes and methods from its parent. Use super() to call methods and constructors from the parent class. Polymorphism lets subclasses override methods to implement custom behavior while keeping the same interface.

Code Examples

Example 1 — Basics

This example introduces the fundamental syntax and concepts.

python
class Vehicle:
    def start(self): return 'Engine started'

class Car(Vehicle):
    pass

Example 2 — Everyday Usage

This example demonstrates a realistic scenario handling business parameters.

python
class User:
    def __init__(self, username):
        self.username = username
    def get_role(self): return 'Guest'

class Admin(User):
    def __init__(self, username, level):
        super().__init__(username) # Call parent constructor
        self.level = level
    def get_role(self): return 'Admin'

adm = Admin('alex', 3)
print(adm.username, adm.get_role())

Example 3 — Advanced Example

This example shows clean, production-grade code structure following senior development standards.

python
class MessageSender:
    def send(self, recipient, body):
        raise NotImplementedError('Subclasses must implement send')

class EmailSender(MessageSender):
    def send(self, recipient, body):
        print(f'Email sent to {recipient}: {body}')

class SMSSender(MessageSender):
    def send(self, recipient, body):
        print(f'SMS sent to {recipient}: {body}')

# Polymorphic function calling identical send interface
def alert_user(senders, user, text):
    for s in senders:
        s.send(user, text)

alert_user([EmailSender(), SMSSender()], 'alex@corp.com', 'System down')

Visual Flow

The following execution flow represents the step-by-step evaluation inside the interpreter:

text
Call method → Check subclass → Found? Run method : Check parent classes → Run parent method

Common Mistakes

Review these common pitfalls when working with this topic:

  • Forgetting to call super().init() in subclass constructors, which leaves parent attributes uninitialized.
  • Creating deeply nested inheritance hierarchies that are hard to understand.
  • Modifying overridden method signatures, which breaks polymorphic interfaces.
  • Using multiple inheritance without understanding how Python searches parents (MRO).

Best Practices

Enforce these Pythonic best practices in your codebase:

❌ Don't
python
class Child(Parent):
    def __init__(self, val):
        self.val = val # Parent attributes remain uninitialized
✅ Do
python
class Child(Parent):
    def __init__(self, val):
        super().__init__()
        self.val = val # Initializes parent attributes correctly

Quick Revision

Use these key summaries for last-minute revision:

  • Inheritance reuse code from parent classes.
  • super() invokes parent constructors and methods.
  • Subclasses can override parent methods.
  • Polymorphism allows different classes to share interfaces.
  • Inheritance search order is determined by MRO.
  • Prefer simple structure compositions.