Inheritance

Updated Nov 22, 2025

Inheritance

Inheritance allows you to create a new class based on an existing class. The new class (child) inherits all the attributes and methods from the parent class, and you can add new features or modify existing ones.

Think of it like a family tree - a child inherits traits from parents but can also have their own unique features.

To demonstrate inheritance, consider the following example where we want to represent different types of vehicles:

❌ Without Inheritance

# vehicles.py class Car: def __init__(self, brand, model): self.brand = brand self.model = model self.wheels = 4 def start(self): print(f"{self.brand} {self.model} car is starting...") def drive(self): print(f"{self.brand} {self.model} car is driving...") class Motorcycle: def __init__(self, brand, model): self.brand = brand self.model = model self.wheels = 2 def start(self): print(f"{self.brand} {self.model} motorcycle is starting...") def drive(self): print(f"{self.brand} {self.model} motorcycle is driving...") class Truck: def __init__(self, brand, model): self.brand = brand self.model = model self.wheels = 6 def start(self): print(f"{self.brand} {self.model} truck is starting...") def drive(self): print(f"{self.brand} {self.model} truck is driving...")

Problem: We're repeating the same code (brand, model, start, drive) in every class. If we want to change how vehicles work, we have to update multiple places.

✅ With Inheritance

# vehicle.py class Vehicle: def __init__(self, brand, model, wheels): self.brand = brand self.model = model self.wheels = wheels def start(self): print(f"{self.brand} {self.model} is starting...") def drive(self): print(f"{self.brand} {self.model} is driving...")
# car.py from vehicle import Vehicle class Car(Vehicle): def __init__(self, brand, model): super().__init__(brand, model, wheels=4) # Call parent's __init__ def honk(self): print(f"{self.brand} {self.model} is honking!")
# motorcycle.py from vehicle import Vehicle class Motorcycle(Vehicle): def __init__(self, brand, model): super().__init__(brand, model, wheels=2) def wheelie(self): print(f"{self.brand} {self.model} is doing a wheelie!")
# truck.py from vehicle import Vehicle class Truck(Vehicle): def __init__(self, brand, model): super().__init__(brand, model, wheels=6) def load_cargo(self): print(f"{self.brand} {self.model} is loading cargo...")
# main.py from car import Car from motorcycle import Motorcycle from truck import Truck car = Car("Toyota", "Camry") car.start() car.drive() car.honk() motorcycle = Motorcycle("Honda", "CBR") motorcycle.start() motorcycle.drive() motorcycle.wheelie() truck = Truck("Ford", "F-150") truck.start() truck.drive() truck.load_cargo()

Now:

  • All vehicles inherit common features from Vehicle.
  • Each vehicle type can have its own unique methods.
  • Changes to Vehicle automatically apply to all child classes.

This approach makes the code:

  • DRY (Don't Repeat Yourself) - no code duplication
  • ✅ Easier to maintain - update once, affects all
  • ✅ More organized - clear hierarchy

🎁 Bonus: Types of Inheritance, super(), and MRO in Python

Types of Inheritance in Python

Python supports several inheritance types:

Single Inheritance

One parent → one child

class A: pass class B(A): pass

Multilevel Inheritance

Grandparent → Parent → Child

class A: pass class B(A): pass class C(B): pass

Hierarchical Inheritance

One parent → multiple children

class A: pass class B(A): pass class C(A): pass

Multiple Inheritance

Child inherits from multiple parents

class A: pass class B: pass class C(A, B): pass

The super() Keyword (Simple Explanation)

super() lets a child class call methods from its parent class.

class Vehicle: def __init__(self, brand): self.brand = brand class Car(Vehicle): def __init__(self, brand, model): super().__init__(brand) self.model = model

Why use super()?

  • Avoid repeating parent logic
  • Cleaner inheritance
  • Works correctly with multiple inheritance through MRO

MRO (Method Resolution Order)

MRO defines the order Python follows to search for methods.

Example:

class A: pass class B: pass class C(A, B): pass print(C.mro())

Purpose of MRO:

  • Decides which class is checked first
  • Prevents confusion in multiple inheritance
  • Follows C3 Linearization (Python handles it automatically)

Quick Summary

  • Types: Single, Multilevel, Hierarchical, Multiple
  • super() calls parent methods cleanly
  • MRO decides method lookup order, especially in multiple inheritance