Python - Inheritance

Overview

Estimated time: 25–35 minutes

Use inheritance to reuse behavior and specialize subclasses. Learn when to prefer composition.

Learning Objectives

  • Define base and derived classes; override methods.
  • Use super() to delegate to parent implementations.
  • Choose composition over inheritance when appropriate.

Prerequisites

Basic inheritance

class Shape:
    def area(self) -> float:
        return 0.0

class Rectangle(Shape):
    def __init__(self, w: float, h: float):
        self.w = w; self.h = h
    def area(self) -> float:
        return self.w * self.h

print(Rectangle(3, 4).area())

Using super()

class Logger:
    def log(self, msg: str) -> None:
        print(f"LOG: {msg}")

class TimestampLogger(Logger):
    def log(self, msg: str) -> None:
        from datetime import datetime
        super().log(f"{datetime.now().isoformat()} - {msg}")

TimestampLogger().log("hello")

Composition over inheritance

class Service:
    def __init__(self, logger: Logger):
        self.logger = logger
    def run(self):
        self.logger.log("running")

Service(TimestampLogger()).run()

Common Pitfalls

  • Deep inheritance hierarchies; prefer shallow trees and clear responsibilities.
  • Forgetting to call super().__init__ in cooperative multiple inheritance.

Checks for Understanding

  1. What does super() do?
  2. When might composition be a better fit than inheritance?
Show answers
  1. It delegates to the next method in the MRO, typically the parent implementation.
  2. When you want to reuse behavior without creating an "is-a" relationship.

Exercises

  1. Create an Employee base class and a Manager subclass that overrides a method.
  2. Refactor an inheritance use into composition and compare readability.