Skip to content
LowLevelDesign Mastery

Inheritance

Reuse code and build relationships between classes.

Video Explanation

Inheritance in OOP Explained

Watch on YouTube

Inheritance is a mechanism where a new class (derived class or subclass) inherits attributes and methods from an existing class (base class or superclass). This allows you to create a hierarchy of classes that share common functionality while allowing specialization.

Inheritance creates an “is-a” relationship. For example:

  • A Car is-a Vehicle
  • A Dog is-an Animal
  • A Manager is-an Employee
💡 Tip: Click dropdown to switch between languages
basic_inheritance.py
class Vehicle:
"""Base class (parent/superclass)"""
def __init__(self, brand: str, model: str, year: int):
self.brand = brand
self.model = model
self.year = year
def start(self):
return f"{self.brand} {self.model} started."
def stop(self):
return f"{self.brand} {self.model} stopped."
def get_info(self):
return f"{self.brand} {self.model} ({self.year})"
class Car(Vehicle):
"""Derived class (child/subclass) - inherits from Vehicle"""
def __init__(self, brand: str, model: str, year: int, num_doors: int):
super().__init__(brand, model, year) # Call parent constructor
self.num_doors = num_doors # Additional attribute
def honk(self):
"""New method specific to Car"""
return "Beep beep!"
class Motorcycle(Vehicle):
"""Another derived class"""
def __init__(self, brand: str, model: str, year: int, bike_type: str):
super().__init__(brand, model, year)
self.bike_type = bike_type # Additional attribute
def wheelie(self):
"""New method specific to Motorcycle"""
return "Doing a wheelie!"
# Usage
car = Car("Toyota", "Camry", 2020, 4)
print(car.start()) # Inherited method: "Toyota Camry started."
print(car.honk()) # Car-specific method: "Beep beep!"
print(car.get_info()) # Inherited method: "Toyota Camry (2020)"
motorcycle = Motorcycle("Yamaha", "YZF-R3", 2021, "Sport")
print(motorcycle.start()) # Inherited method: "Yamaha YZF-R3 started."
print(motorcycle.wheelie()) # Motorcycle-specific method: "Doing a wheelie!"
Basic inheritance: Car and Motorcycle extend a Vehicle base class, adding num_doors with honk and bike_type with wheelie

Subclasses can override parent methods to provide specialized behavior:

💡 Tip: Click dropdown to switch between languages
method_overriding.py
class Vehicle:
def __init__(self, brand: str, model: str, year: int):
self.brand = brand
self.model = model
self.year = year
def start(self):
return f"{self.brand} {self.model} started."
def fuel_type(self):
return "Unknown fuel type"
class Car(Vehicle):
def start(self):
"""Override parent method with specialized behavior"""
return f"{self.brand} {self.model} car started with a roar!"
def fuel_type(self):
"""Override to specify fuel type"""
return "Gasoline or Electric"
class ElectricCar(Car):
def start(self):
"""Further override for electric cars"""
return f"{self.brand} {self.model} silently started (electric motor)"
def fuel_type(self):
"""Override to specify electric"""
return "Electric"
car = Car("Toyota", "Camry", 2020)
print(car.start()) # "Toyota Camry car started with a roar!"
print(car.fuel_type()) # "Gasoline or Electric"
electric_car = ElectricCar("Tesla", "Model 3", 2023)
print(electric_car.start()) # "Tesla Model 3 silently started (electric motor)"
print(electric_car.fuel_type()) # "Electric"

The super() function/keyword allows you to call methods from the parent class:

💡 Tip: Click dropdown to switch between languages
super_example.py
class Employee:
def __init__(self, name: str, employee_id: int):
self.name = name
self.employee_id = employee_id
def get_info(self):
return f"Employee: {self.name} (ID: {self.employee_id})"
class Manager(Employee):
def __init__(self, name: str, employee_id: int, department: str):
super().__init__(name, employee_id) # Call parent __init__
self.department = department
def get_info(self):
"""Extend parent method using super()"""
base_info = super().get_info() # Call parent method
return f"{base_info}, Department: {self.department}"
class Director(Manager):
def __init__(self, name: str, employee_id: int, department: str, budget: float):
super().__init__(name, employee_id, department) # Call Manager's __init__
self.budget = budget
def get_info(self):
"""Further extend using super()"""
manager_info = super().get_info() # Call Manager's get_info
return f"{manager_info}, Budget: ${self.budget:,.2f}"
manager = Manager("Alice", 101, "Engineering")
print(manager.get_info())
# "Employee: Alice (ID: 101), Department: Engineering"
director = Director("Bob", 102, "Engineering", 1000000.0)
print(director.get_info())
# "Employee: Bob (ID: 102), Department: Engineering, Budget: $1,000,000.00"
💡 Tip: Click dropdown to switch between languages
ecommerce_inheritance.py
class Product:
"""Base class for all products"""
def __init__(self, name: str, price: float, sku: str):
self.name = name
self.price = price
self.sku = sku
def calculate_shipping(self, weight: float) -> float:
"""Base shipping calculation"""
return weight * 2.5 # $2.5 per kg
def get_info(self) -> str:
return f"{self.name} - ${self.price:.2f} (SKU: {self.sku})"
class DigitalProduct(Product):
"""Digital products - no shipping"""
def __init__(self, name: str, price: float, sku: str, download_size: float):
super().__init__(name, price, sku)
self.download_size = download_size # in MB
def calculate_shipping(self, weight: float) -> float:
"""Override - digital products have no shipping cost"""
return 0.0
def get_info(self) -> str:
base_info = super().get_info()
return f"{base_info} - Digital Download ({self.download_size} MB)"
class PhysicalProduct(Product):
"""Physical products with weight"""
def __init__(self, name: str, price: float, sku: str, weight: float):
super().__init__(name, price, sku)
self.weight = weight # in kg
def calculate_shipping(self, weight: float = None) -> float:
"""Override - use product's own weight"""
actual_weight = weight if weight else self.weight
return super().calculate_shipping(actual_weight)
def get_info(self) -> str:
base_info = super().get_info()
return f"{base_info} - Weight: {self.weight} kg"
class FragileProduct(PhysicalProduct):
"""Fragile products need special handling"""
def __init__(self, name: str, price: float, sku: str, weight: float):
super().__init__(name, price, sku, weight)
def calculate_shipping(self, weight: float = None) -> float:
"""Override - add handling fee for fragile items"""
base_shipping = super().calculate_shipping(weight)
handling_fee = 10.0 # Additional $10 for fragile items
return base_shipping + handling_fee
def get_info(self) -> str:
base_info = super().get_info()
return f"{base_info} - FRAGILE"
# Usage
ebook = DigitalProduct("Python Guide", 29.99, "DIG-001", 5.2)
print(ebook.get_info())
print(f"Shipping: ${ebook.calculate_shipping(0):.2f}")
book = PhysicalProduct("Python Book", 39.99, "PHY-001", 0.5)
print(book.get_info())
print(f"Shipping: ${book.calculate_shipping():.2f}")
vase = FragileProduct("Ceramic Vase", 49.99, "FRG-001", 1.2)
print(vase.get_info())
print(f"Shipping: ${vase.calculate_shipping():.2f}")
💡 Tip: Click dropdown to switch between languages
multiple_inheritance.py
class Flyable:
def fly(self):
return "Flying through the air"
class Swimmable:
def swim(self):
return "Swimming in water"
class Duck(Flyable, Swimmable):
"""Duck can both fly and swim"""
def __init__(self, name: str):
self.name = name
def quack(self):
return f"{self.name} says quack!"
duck = Duck("Donald")
print(duck.fly()) # From Flyable
print(duck.swim()) # From Swimmable
print(duck.quack()) # Duck's own method
💡 Tip: Click dropdown to switch between languages

When using multiple inheritance, Python uses Method Resolution Order to determine which method to call:

mro_example.py
class A:
def method(self):
return "A"
class B(A):
def method(self):
return "B"
class C(A):
def method(self):
return "C"
class D(B, C):
pass
d = D()
print(d.method()) # "B" - B comes before C in MRO
print(D.__mro__) # Shows the method resolution order
  • Inheritance creates an “is-a” relationship between classes
  • Subclasses inherit all attributes and methods from parent classes
  • Method overriding allows subclasses to provide specialized behavior
  • super() is used to call parent class methods
  • Multiple inheritance allows a class to inherit from multiple parents
  • MRO determines the order in which methods are resolved in multiple inheritance
  • Use inheritance to reuse code and create specialized classes from general ones

Inheritance is powerful for creating class hierarchies where specialized classes extend and customize the behavior of more general classes.

💡 Time to Practice!

Now that you understand the concepts, put them into practice with our interactive playground. Build UML diagrams, write code, and get AI-powered feedback.

Browse All Problems