๐Ÿงฌ Python OOP

Python Inheritance

A complete beginner-friendly guide to inheritance in Python โ€” covering single, multiple, multilevel, hierarchical, and hybrid inheritance, the super() function, method overriding, and Method Resolution Order (MRO) for 2026.

๐Ÿ“…

Last Updated

March 2026

โฑ๏ธ

Read Time

27 min

๐ŸŽฏ

Level

Beginner

What is Inheritance in Python?

Inheritance is an object-oriented mechanism that lets one class acquire the attributes and methods of another class. The class being inherited from is called the parent class (or base/superclass), and the class that inherits is called the child class (or derived/subclass). Inheritance lets you build new, specialised classes on top of existing general ones, without rewriting shared logic from scratch.

Think of it like a family tree of blueprints. A general Vehicle blueprint might describe that every vehicle has a brand and can move. A more specific Car blueprint can inherit everything from Vehicle and then add its own details โ€” like a trunk or four doors โ€” without redrawing the parts it already shares with every other vehicle. This relationship is often summarised as an "is-a" relationship: a Car is a Vehicle.

In Python, inheritance is declared simply by placing the parent class name in parentheses after the child class name: class Car(Vehicle):. From that moment on, every attribute and method defined on Vehicle is automatically available on Car as well, unless Car chooses to override it with its own version.

Inheritance is one of the four foundational pillars of OOP, alongside Encapsulation, Abstraction, and Polymorphism. It is arguably the pillar most responsible for Python's reputation for code reuse โ€” well-designed inheritance hierarchies let large systems avoid duplicating logic across dozens of similar classes, which is a major reason frameworks like Django rely on it so heavily.

How Inheritance Evolved in Python

Inheritance has been part of Python since its very first release, but the rules governing how it resolves conflicts and interacts with the rest of the language have been refined substantially over the decades. Here is a timeline of the key milestones:

  • โ–ถ

    1991 โ€” Python 0.9.0 already supported multiple inheritance from its earliest public release, a bold design choice that many later mainstream languages deliberately avoided.

  • โ–ถ

    1995-2000 โ€” Early 'classic classes' resolved multiple inheritance using a simple depth-first, left-to-right search, which could produce confusing or inconsistent results in complex hierarchies.

  • โ–ถ

    2001 โ€” Python 2.2 introduced new-style classes and, alongside them, the C3 linearisation algorithm for calculating a class's Method Resolution Order (MRO), fixing long-standing inconsistencies in multiple inheritance.

  • โ–ถ

    2001 โ€” The super() function was introduced in the same release, initially requiring explicit arguments like super(Car, self).

  • โ–ถ

    2008 โ€” Python 3.0 simplified super() to a zero-argument form โ€” just super() โ€” making constructor and method chaining far less verbose and error-prone.

  • โ–ถ

    2015 โ€” PEP 484 type hints allowed inheritance relationships to be checked more rigorously by static type checkers like mypy, catching subclassing mistakes before runtime.

  • โ–ถ

    2019 โ€” Python 3.8 introduced Protocol classes via typing.Protocol, enabling 'structural' inheritance-like behaviour (duck typing with type checking) without requiring formal class inheritance.

  • โ–ถ

    2022-2026 โ€” Python 3.11 through 3.14 focused on faster attribute lookup across inheritance chains and continued refinement of typing.Self, making inherited method chains both faster and easier to type-check accurately.

Types of Inheritance in Python

Python supports every classic form of inheritance found in object-oriented design. Understanding each type โ€” and when to use it โ€” is essential to designing clean class hierarchies.

1๏ธโƒฃ
Single Inheritance

One child class inherits from exactly one parent class. This is the simplest and most common form, e.g. class Car(Vehicle):.

๐Ÿ”ข
Multiple Inheritance

One child class inherits from more than one parent class at once, e.g. class Sedan(Car, LuxuryFeatures):. Python resolves conflicts using MRO.

๐Ÿชœ
Multilevel Inheritance

A chain of inheritance across several levels, e.g. Vehicle โ†’ Car โ†’ SportsCar, where each class inherits from the one directly above it.

๐ŸŒณ
Hierarchical Inheritance

Multiple child classes all inherit from the same single parent class, e.g. Car, Truck, and Motorcycle all inheriting from Vehicle.

๐Ÿ•ธ๏ธ
Hybrid Inheritance

A combination of two or more inheritance types in one hierarchy, such as mixing hierarchical and multiple inheritance together in the same design.

๐Ÿ”—
super() Function

Lets a child class call methods (especially __init__) from its parent class, enabling clean chaining without hard-coding the parent's class name.

๐ŸŽญ
Method Overriding

A child class redefining a method that already exists in its parent, replacing the inherited behaviour with its own specialised version.

๐Ÿงฉ
MRO (Method Resolution Order)

The precise order Python searches through a class hierarchy when looking up a method or attribute, calculated using the C3 linearisation algorithm.

๐Ÿ”
isinstance() and issubclass()

Built-in functions for checking whether an object belongs to a class (or its subclasses), and whether one class is a subclass of another.

๐ŸงŠ
Abstract Base Classes (ABC)

Classes designed to be inherited from but never instantiated directly, defined using the abc module, forcing subclasses to implement specific methods.

How Method Lookup Works Through Inheritance โ€” Flowchart

When you call a method on an object, Python doesn't just look at that object's own class โ€” it searches up through the entire inheritance chain until it finds a matching method. The flowchart below traces exactly how this search happens.

๐Ÿ“ž Call a Methodmy_sports_car.honk()
lookup begins
๐Ÿ” Check Own ClassDoes SportsCar define honk()?
yes, found here
โœ… Found โ€” Use ItMethod runs immediately
runs on object
๐Ÿ” Check Parent ClassDoes Car define honk()?
no, search up
๐Ÿ” Check GrandparentDoes Vehicle define honk()?
yes, found here
๐Ÿšซ Not Found AnywhereRaises AttributeError
๐Ÿ–จ๏ธ Method ExecutesUsing the first match found

Code Execution Flow โ€” from source to output

Key insight: Python always uses the first matching method found, searching starting from the object's own class and moving upward through its parents in the exact order defined by the MRO. This is precisely how method overriding works โ€” a child class's version is found first, so it "wins" over the parent's version further up the chain.

How Python Inheritance Works โ€” super(), Overriding, and MRO Explained

Three concepts sit at the heart of practical Python inheritance: the super() function, method overriding, and Method Resolution Order (MRO). Understanding these three deeply is what separates a beginner who can write class Car(Vehicle): from someone who can confidently design a multi-level class hierarchy.

๐Ÿ”— The super() Function

super() gives a child class a way to call methods defined on its parent class, without hard-coding the parent's class name directly. It is most commonly used inside a child's __init__ to reuse the parent's initialisation logic: super().__init__(brand) runs Vehicle's constructor before Car's own constructor adds its specific attributes. Using super() instead of writing Vehicle.__init__(self, brand) directly makes code more maintainable โ€” if the parent class is ever renamed or the hierarchy restructured, super() automatically adapts, while a hard-coded class name would not.

๐ŸŽญ Method Overriding

Method overriding happens when a child class defines a method with the exact same name as one already defined in its parent class. The child's version takes priority whenever the method is called on a child object, effectively replacing โ€” or 'overriding' โ€” the parent's behaviour. This is how a general Vehicle.describe() method can produce a generic description, while Car.describe() produces a more specific one, even though both classes use the same method name.

Overriding does not have to completely discard the parent's logic โ€” a common and highly recommended pattern is to call super().method_name() inside the override, extending the parent's behaviour rather than replacing it entirely. For example, an overridden describe() method might call super().describe() to get the base description, then append extra Car-specific details onto it.

๐Ÿงฉ Method Resolution Order (MRO)

MRO is the precise, deterministic order Python follows when searching through a class hierarchy to find a method or attribute. For simple single inheritance, MRO is intuitive โ€” search the class itself, then its parent, then its grandparent, and so on. For multiple inheritance, where a class has more than one parent, MRO becomes essential for resolving which parent's version of a shared method name actually gets used. Python calculates MRO using the C3 linearisation algorithm, which guarantees a consistent, predictable order even in complex hierarchies. You can inspect any class's MRO directly using ClassName.__mro__ or ClassName.mro().

๐Ÿ” isinstance() and issubclass()

isinstance(obj, ClassName) checks whether an object belongs to a given class or any of its subclasses, returning True or False. issubclass(ChildClass, ParentClass) checks whether one class inherits from another, without needing an actual object. Both functions respect the full inheritance chain โ€” isinstance(my_sports_car, Vehicle) returns True even though my_sports_car is technically a SportsCar, several levels below Vehicle in the hierarchy.

Simple rule to remember: super() lets a child reuse its parent's logic. Overriding lets a child replace or extend a parent's method. MRO decides exactly which version of a method wins when there's more than one candidate in the hierarchy.

Single vs Multiple vs Multilevel Inheritance โ€” Key Differences

Beginners often mix up these related-but-different inheritance structures. This table lays out exactly how they differ.

FeatureSingle InheritanceMultiple InheritanceMultilevel Inheritance
Number of direct parentsExactly oneTwo or moreOne (per level)
Structure shapeOne parent โ†’ one childSeveral parents โ†’ one childA chain of several levels
Syntax exampleclass Car(Vehicle):class Sedan(Car, LuxuryFeatures):class SportsCar(Car): (where Car(Vehicle):)
Conflict riskVery lowHigh โ€” needs MRO to resolveLow โ€” but attributes can shadow across levels
Common real-world useMost everyday class designMixins adding optional behaviourSpecialising a general class step by step
MRO complexitySimple, linear chainRequires C3 linearisationSimple, linear chain
ReadabilityEasiest to followCan become confusing if overusedEasy, if not too many levels deep

Python Inheritance vs Other Languages โ€” Comparison

Not every object-oriented language treats inheritance the same way. This table compares how Python's approach differs from other popular languages.

FeaturePythonJavaC++JavaScript
Multiple inheritanceโœ… Directly supportedโŒ Interfaces onlyโœ… Directly supportedโŒ Not supported directly
Conflict resolutionMRO (C3 linearisation)Not applicable (no multiple inheritance)Explicit scope resolution (::)Not applicable
Calling parent methodsuper().method()super.method()ParentClass::method()super.method()
Interfaces / Protocolstyping.Protocol (structural)interface keywordAbstract classes onlyNo formal interfaces
Abstract classesabc.ABC moduleabstract keywordPure virtual functionsNo native support
Access to overridden parent methodAlways possible via super()Always possible via superAlways possible via scope resolutionAlways possible via super
Runtime type checkingisinstance() / issubclass()instanceofdynamic_cast / typeidinstanceof

Advantages and Disadvantages of Inheritance

Inheritance is one of the most powerful tools in object-oriented design, but overusing it can create its own problems. Understanding both sides helps you decide when inheritance genuinely improves your code.

โœ… Advantages
Maximises Code ReuseShared logic is written once in a parent class and automatically available to every subclass, avoiding duplicated code across similar classes.
Models Natural HierarchiesMany real-world domains genuinely have 'is-a' relationships โ€” a Car is a Vehicle, a Manager is an Employee โ€” which inheritance represents cleanly.
Enables PolymorphismCode written to operate on a general parent type automatically works with any subclass, reducing the need for repetitive type-checking logic.
Simplifies MaintenanceFixing a bug in shared parent logic automatically fixes it for every subclass, rather than requiring the same fix to be applied in multiple places.
Supports Framework DesignDjango's models, Flask's views, and countless other frameworks are built around users inheriting from provided base classes to gain built-in functionality.
Encourages Consistent InterfacesAbstract base classes can enforce that every subclass implements certain required methods, keeping a codebase's structure predictable.
โŒ Disadvantages
Tight Coupling Between ClassesA subclass becomes dependent on its parent's internal implementation details, so changes to the parent can unexpectedly break subclasses.
Deep Hierarchies Are Hard to FollowTracing a single method call through five or six levels of inheritance can make code significantly harder to understand and debug.
Multiple Inheritance ComplexityMRO conflicts, the 'diamond problem,' and unexpected method resolution can confuse even experienced developers in complex hierarchies.
Fragile Base Class ProblemA seemingly harmless change to a widely-inherited parent class can silently break many subclasses that depended on its previous exact behaviour.
Overused for Code Reuse AloneDevelopers sometimes reach for inheritance purely to reuse code, even when there's no genuine 'is-a' relationship, when composition would be a cleaner fit.
Slightly Slower Attribute LookupSearching up through a deep inheritance chain to find a method takes marginally longer than a direct lookup on a flat class, though this rarely matters in practice.

Inheritance Hierarchy Architecture โ€” Vehicle Family Example

The diagram below shows a realistic multi-level inheritance hierarchy, illustrating how a general Vehicle class flows down into increasingly specialised classes, and how hierarchical inheritance branches into multiple siblings at the same level.

Base Class (Level 0)
class Vehicle:brand, speed attributesdef move(self), def describe(self)
Hierarchical Children (Level 1)
class Car(Vehicle):class Truck(Vehicle):class Motorcycle(Vehicle):
Multilevel Specialisation (Level 2)
class SportsCar(Car):class PickupTruck(Truck):Adds turbo, cargo_capacity, etc.
Mixin / Multiple Inheritance
class ElectricMixin:class ElectricCar(Car, ElectricMixin):MRO resolves shared method names
super() Chain
SportsCar.__init__ โ†’ super()Car.__init__ โ†’ super()Vehicle.__init__ (base case)
Runtime Objects
my_sports_car โ†’ SportsCar instanceisinstance(my_sports_car, Vehicle) โ†’ TrueInherited + overridden methods available

Architecture Diagram

Your First Python Inheritance Example

Below is a complete, realistic example demonstrating single inheritance, super().__init__(), and method overriding together in a Vehicle-to-Car hierarchy.

๐Ÿ Pythoninheritance.py
class Vehicle:
    def __init__(self, brand, speed=0):
        self.brand = brand
        self.speed = speed

    def describe(self):
        return f"{self.brand} moving at {self.speed} km/h"


class Car(Vehicle):
    def __init__(self, brand, model, speed=0):
        super().__init__(brand, speed)   # Reuse Vehicle's constructor
        self.model = model

    def describe(self):                  # Method overriding
        base_description = super().describe()   # Extend, not replace
        return f"{base_description} โ€” Model: {self.model}"


car1 = Car("Tesla", "Model 3", 60)
print(car1.describe())
print(isinstance(car1, Vehicle))
print(issubclass(Car, Vehicle))

Output

Tesla moving at 60 km/h โ€” Model: Model 3 True True

Practice This Code โ€” Live Editor

Line-by-Line Explanation

  • โ–ถ

    class Car(Vehicle): โ€” Declares that Car inherits from Vehicle, gaining access to everything Vehicle defines.

  • โ–ถ

    super().__init__(brand, speed) โ€” Calls Vehicle's constructor first, reusing its logic instead of duplicating self.brand = brand manually.

  • โ–ถ

    def describe(self): (inside Car) โ€” Overrides Vehicle's describe() method with a more specific version.

  • โ–ถ

    super().describe() โ€” Inside the override, calls the parent's original describe() to extend it rather than fully replacing it.

  • โ–ถ

    isinstance(car1, Vehicle) โ€” Returns True because car1, though a Car, is also considered a Vehicle through inheritance.

  • โ–ถ

    issubclass(Car, Vehicle) โ€” Returns True, confirming Car genuinely inherits from Vehicle at the class level.

Multiple Inheritance and MRO in Action

Multiple inheritance becomes especially useful with mixins โ€” small classes designed to add one specific piece of behaviour, meant to be combined with other classes rather than used on their own. The example below shows a Car combined with an ElectricMixin.

๐Ÿ Pythonmultiple_inheritance.py
class Car:
    def __init__(self, brand):
        self.brand = brand

    def info(self):
        return f"Car: {self.brand}"


class ElectricMixin:
    def info(self):
        base = super().info()
        return f"{base} (Electric)"


class ElectricCar(ElectricMixin, Car):
    pass


car1 = ElectricCar("Tesla")
print(car1.info())
print(ElectricCar.__mro__)

Output

Car: Tesla (Electric) (<class '__main__.ElectricCar'>, <class '__main__.ElectricMixin'>, <class '__main__.Car'>, <class 'object'>)

Notice the order in class ElectricCar(ElectricMixin, Car): matters enormously. Because ElectricMixin is listed first, Python's MRO places it before Car in the search order, so ElectricMixin.info() runs first โ€” and its own internal super().info() call then reaches Car.info() next, producing the combined result. Reversing the parent order would change which info() runs first entirely.

Where Inheritance Is Used โ€” Real-World Applications

Inheritance isn't just a theoretical OOP concept โ€” it's the structural backbone of many of the most widely used Python frameworks and libraries. Here's where it shows up in practice:

  • โ–ถ

    ๐ŸŒ Django Model & View Inheritance โ€” Every Django model inherits from models.Model, gaining database functionality automatically. Class-based views inherit from generic views like ListView or DetailView to gain pre-built behaviour.

  • โ–ถ

    ๐Ÿง  PyTorch Neural Network Modules โ€” Every custom neural network in PyTorch inherits from nn.Module, gaining parameter tracking, GPU support, and serialisation for free, while defining its own forward() method.

  • โ–ถ

    ๐Ÿงช Python's Own Exception Hierarchy โ€” Built-in exceptions like ValueError and TypeError all inherit from the base Exception class, letting a single except Exception: catch any of them, while more specific except blocks catch only particular subtypes.

  • โ–ถ

    ๐Ÿ–ฅ๏ธ GUI Widget Hierarchies โ€” Tkinter and PyQt build entire widget libraries through inheritance โ€” a custom button class might inherit from a base Button class to add specialised styling or behaviour.

  • โ–ถ

    ๐Ÿงฉ Abstract Base Classes for Plugins โ€” Plugin systems often define an abstract base class specifying required methods, forcing every plugin (subclass) to implement a consistent interface the main application can rely on.

  • โ–ถ

    ๐ŸŽฎ Game Entity Hierarchies โ€” A game might define a general GameObject base class, with Player, Enemy, and Projectile all inheriting shared position and rendering logic while adding their own specialised behaviour.

  • โ–ถ

    ๐Ÿงพ Pydantic & Data Validation Models โ€” FastAPI and Pydantic rely heavily on inheritance, letting developers build specialised request/response models on top of shared base schemas.

  • โ–ถ

    โ˜๏ธ Cloud SDK Client Hierarchies โ€” SDKs like boto3 often structure different service clients (S3, EC2, Lambda) using shared base classes for authentication and request handling, with service-specific subclasses adding their own methods.

Why Should You Master Inheritance in 2026?

Inheritance shows up everywhere in professional Python development, from the smallest exception hierarchy to the largest web framework. Here's why it deserves serious study:

  • โ–ถ

    ๐Ÿ“š Essential for Reading Framework Code โ€” Django, FastAPI, PyTorch, and nearly every major framework expect you to inherit from their base classes โ€” understanding inheritance is non-negotiable for using them effectively.

  • โ–ถ

    ๐Ÿงฉ Reduces Duplicate Code โ€” Well-designed inheritance hierarchies dramatically cut down on repeated logic across related classes, making codebases smaller and easier to maintain.

  • โ–ถ

    ๐ŸŽญ Unlocks Polymorphism โ€” Inheritance is the foundation polymorphism is built on; without understanding inheritance first, polymorphic code patterns are much harder to grasp.

  • โ–ถ

    ๐Ÿ’ผ A Staple Interview Topic โ€” MRO, super(), method overriding, and the difference between inheritance types are classic Python OOP interview questions at nearly every experience level.

  • โ–ถ

    ๐Ÿ—๏ธ Enables Extensible Design โ€” Systems designed with inheritance in mind (like abstract base classes for plugins) let new functionality be added by writing new subclasses, without touching existing code.

  • โ–ถ

    ๐Ÿง  Deepens Your Understanding of Python's Own Design โ€” Python's exception system, container types, and even numeric types are all connected through inheritance โ€” understanding it illuminates how Python itself is built.

Python Versions and Inheritance-Related Features

Inheritance mechanics have been refined steadily across Python's history. Here's a quick reference of version-specific milestones relevant to how inheritance works today:

  • โ–ถ

    Python 2.2 โ€” New-Style Classes & C3 Linearisation โ€” Introduced the modern, predictable MRO algorithm that resolves multiple inheritance consistently, replacing the older, less reliable depth-first search.

  • โ–ถ

    Python 3.0 โ€” Zero-Argument super() โ€” Simplified super(Car, self).method() down to super().method(), removing a significant source of boilerplate and copy-paste errors in inheritance chains.

  • โ–ถ

    Python 3.4 โ€” abc Module Improvements โ€” Strengthened support for Abstract Base Classes, making it easier to define required methods that every subclass must implement.

  • โ–ถ

    Python 3.6 โ€” __init_subclass__ Hook โ€” Added a special method that runs automatically whenever a class is subclassed, useful for registering plugins or validating subclass structure without decorators.

  • โ–ถ

    Python 3.8 โ€” typing.Protocol โ€” Introduced structural subtyping ('if it walks like a duck'), letting code type-check against an interface without requiring formal class inheritance.

  • โ–ถ

    Python 3.11 โ€” typing.Self โ€” Improved type hinting for methods that return an instance of their own class, especially useful in fluent, chainable subclass hierarchies.

  • โ–ถ

    Python 3.12-3.14 โ€” Performance Improvements โ€” Faster attribute and method lookup across deep inheritance chains, reducing the small performance cost that once came with heavily-layered class hierarchies.

VersionReleasedInheritance-Related Feature
Python 2.22001C3 linearisation MRO introduced
Python 3.02008Zero-argument super()
Python 3.42014Stronger Abstract Base Class support
Python 3.62016__init_subclass__ hook
Python 3.82019typing.Protocol structural subtyping
Python 3.112022typing.Self for chained subclass methods
Python 3.132024Faster inheritance-chain attribute lookup

Python Inheritance โ€” Interview Questions (Beginner Level)

These are the most frequently asked interview questions about Python inheritance for freshers and beginner-level positions. Review these carefully before your next Python OOP interview.

Practice Questions โ€” Test Your Understanding

Test your grasp of Python inheritance with these practice questions. Try answering each one yourself before checking the answer โ€” active recall builds much stronger, longer-lasting understanding than passive reading.

1. If class Car(Vehicle): does not define its own __init__, what happens when you create a Car object?

Easy

2. In class ElectricCar(ElectricMixin, Car):, why does the order of ElectricMixin and Car matter?

Medium

3. What does ClassName.__mro__ return, and how would you use it to debug an unexpected method call?

Hard

4. Why might calling Vehicle.__init__(self, brand) directly, instead of using super().__init__(brand), cause problems in multiple inheritance?

Hard

5. What is the difference between overriding a method completely versus extending it with super()?

Medium

6. If Truck and Car both inherit from Vehicle (hierarchical inheritance), does changing Truck affect Car in any way?

Easy

7. Why would you use an Abstract Base Class instead of a regular parent class with 'placeholder' methods?

Hard

8. What would issubclass(Vehicle, Car) return, given class Car(Vehicle):, and why?

Medium

Conclusion โ€” Why Inheritance Matters

Inheritance is what turns a collection of isolated classes into a coherent, extensible family of related types. It is how Django lets you build a fully functional model in a handful of lines, how PyTorch lets you define a neural network by inheriting from nn.Module, and how Python's own exception system lets a single except block gracefully catch an entire family of related errors.

The concepts covered here โ€” single, multiple, multilevel, and hierarchical inheritance, the super() function, method overriding, and Method Resolution Order (MRO) โ€” together form the toolkit needed to design class hierarchies that are both powerful and maintainable, rather than tangled and fragile.

Your GoalShould You Master Inheritance?
Working with Django or FastAPIโœ… Absolutely โ€” both rely on inheriting from base classes
Building neural networks in PyTorchโœ… Yes โ€” every model inherits from nn.Module
Handling exceptions cleanlyโœ… Yes โ€” Python's exception hierarchy is inheritance-based
Preparing for developer interviewsโœ… Yes โ€” MRO and super() are classic OOP questions
Designing a plugin or extensible systemโœ… Yes โ€” Abstract Base Classes rely entirely on inheritance
Writing a single, isolated utility scriptโš ๏ธ Optional โ€” a plain function may be simpler
Reducing duplicate code across similar classesโœ… Yes โ€” inheritance is built exactly for this purpose
Avoiding tightly coupled, fragile class designsโš ๏ธ Use carefully โ€” composition is sometimes the better fit

The natural next step after mastering inheritance is Polymorphism โ€” learning how code written against a general parent type can seamlessly work with any of its subclasses, unlocking flexible, extensible designs. From there, encapsulation, abstract base classes, and classic design patterns all build directly on the inheritance foundation covered here.

Used thoughtfully, inheritance turns repetition into reuse and complexity into structure. Practice building your own small class hierarchies, experiment with super() and method overriding, and the concepts will click quickly. ๐Ÿงฌ

Frequently Asked Questions (FAQ)