5 Types of Inheritance in Python You Must Understand to Level Up!
By Rohit Sharma
Updated on Oct 30, 2025 | 14 min read | 34K+ views
Share:
Working professionals
Fresh graduates
More
By Rohit Sharma
Updated on Oct 30, 2025 | 14 min read | 34K+ views
Share:
Table of Contents
Did you know? Inheritance in Python was inspired by the concept invented in 1969 for the Simula programming language, which is considered the first object-oriented language. |
Inheritance in Python lets one class access and extend another’s properties and methods. It supports five key structures, Single, Multiple, Multilevel, Hierarchical, and Hybrid inheritance. Each type defines how classes interact, share behavior, and build logical relationships in your code. Understanding these types of inheritance in Python helps you write cleaner, modular programs that scale easily across real-world applications.
In this guide, you’ll read more about the five types of inheritance in Python, how each works with examples, the method resolution order (MRO), and best practices to implement inheritance effectively in your Python projects.
Want to master Python and take your coding skills to the next level? Explore our Online Data Science Course or dive into cutting-edge AI and Machine Learning Courses to build real-world skills and boost your career in tech.
In Python, inheritance is the mechanism by which one class (the child class or derived class) acquires the properties and methods of another class (the parent class or base class).
The child class can use all the features of the parent class and can also add its own unique features or "override" the parent's features to behave differently. This "is-a" relationship (e.g., "a Dog is-a Animal") is the core of inheritance.
Popular Data Science Programs
The syntax for inheritance in Python is straightforward. You define the child class and place the parent class's name inside parentheses after it:
Python
# Parent class (Base class)
class Parent:
def parent_method(self):
print("This is the Parent class.")
# Child class (Derived class)
class Child(Parent):
def child_method(self):
print("This is the Child class.")
# Create an object of the Child class
obj = Child()
# The child object can access methods from the Parent class
obj.parent_method()
# The child object can also access its own methods
obj.child_method()
Output:
This is the Parent class.
This is the Child class.
Here's a quick comparison of the roles:
| Feature | Parent Class (Base Class) | Child Class (Derived Class) |
| Role | The class being inherited from. | The class that inherits. |
| Purpose | Provides general attributes and methods. | Specializes or extends the parent's functionality. |
| Access | Cannot access child-specific members. | Can access all non-private parent members. |
| Syntax | class Parent: | class Child(Parent): |
Understanding this basic structure is the first step before exploring each type of inheritance in Python.
Also Read: A Complete Guide on OOPs Concepts in Python
Python is a versatile language that supports several inheritance patterns. While some languages (like Java) restrict certain types (like multiple inheritance), Python provides full flexibility.
Here's a brief overview of the 5 types of inheritance in Python that we will cover in detail:
Let's look at a summary of these types of inheritance in Python before we dive into each one.
| Type Name | Definition | Syntax Example | Common Use Case |
| Single | One child class inherits from one parent class. | class Child(Parent): | Creating a specialized version of a class. |
| Multiple | One child class inherits from multiple parent classes. | class Child(Parent1, Parent2): | "Mixins" - adding specific functionalities (e.g., logging, serialization). |
| Multilevel | A class inherits from a derived class (a chain). | class GrandChild(Parent): | Tiered systems, categories (e.g., Electronics -> Phone -> Smartphone). |
| Hierarchical | One parent class is inherited by multiple child classes. | class Child1(Parent): class Child2(Parent): | Grouping related classes (e.g., Account -> SavingsAccount, CheckingAccount). |
| Hybrid | A mix of any two or more inheritance types. | class D(B, C): where B(A) and C(A) | Modeling complex, real-world relationships. |
Also Read: Types of Inheritance in C++ What Should You Know?
Data Science Courses to upskill
Explore Data Science Courses for Career Progression
Single inheritance is the simplest and most common of all the types of inheritance in Python. In this pattern, a child class inherits from only one parent class. It represents a straightforward "is-a" relationship.
The syntax is the one we've already seen. Let's use a more concrete example.
Python
# Parent class
class Animal:
def __init__(self, name):
self.name = name
print(f"Animal '{self.name}' created.")
def speak(self):
print("Animal makes a sound.")
# Child class
class Dog(Animal):
# We can override the parent's method
def speak(self):
print(f"{self.name} says Woof!")
# Create an object of the Child class
my_dog = Dog("Buddy")
# The child object calls its own overridden method
my_dog.speak()
Output:
Animal 'Buddy' created.
Buddy says Woof!
In this example, the Dog class inherits the __init__ method from Animal. When we create Dog("Buddy"), it's the Animal's __init__ that runs. However, Dog provides its own version of the speak method, overriding the parent's version. This is a perfect, simple example of the types of inheritance in Python with example code.
Also Read: A Complete Guide To Method Overloading in Python (With examples)
Use single inheritance whenever you want to create a more specialized version of an existing class.
This is the cleanest and most recommended type of inheritance in Python for most use cases.
Multiple inheritance is a feature that allows a single child class to inherit from two or more parent classes. This means the child class gains all the attributes and methods from all its parents.
You simply list all parent classes in the parentheses, separated by commas.
Python
class Father:
def get_last_name(self):
return "Smith"
class Mother:
def get_eye_color(self):
return "Blue"
# Child inherits from BOTH Father and Mother
class Child(Father, Mother):
pass
# Create an object of the Child class
c = Child()
# It has access to methods from all parents
print(f"Last Name: {c.get_last_name()}")
print(f"Eye Color: {c.get_eye_color()}")
Output:
Last Name: Smith
Eye Color: Blue
A common question with this type of inheritance in Python is: What happens if both Father and Mother have a method with the same name (e.g., get_height())? Which one does Child use?
Python handles this using the Method Resolution Order (MRO). The MRO defines the order in which Python searches the parent classes for a method. It uses an algorithm called C3 linearization. You can view the MRO of any class using the __mro__ attribute.
Python
print(Child.__mro__)
Output:
(<class '__main__.Child'>, <class '__main__.Father'>, <class '__main__.Mother'>, <class 'object'>)
This tuple shows the lookup order. Python checks Child first, then Father, then Mother, and finally the base object class.
| Class | MRO (Lookup Order) |
| Child | 1. Child |
| Father | 2. Father |
| Mother | 3. Mother |
| object | 4. object (the base for all classes) |
Multiple inheritance is powerful but can make code complex. It's most famously used for Mixins. A mixin is a class that provides a specific, isolated piece of functionality (like logging, serialization, or a specific feature) but is not meant to be instantiated on its own. For instance, you could have a CanFly mixin and add it to Bird and Airplane classes. This is one of the most practical types of inheritance in Python with example use cases.
Also Read: Difference Between List and Tuple in Python
In multilevel inheritance, you have a chain of inheritance. A derived class inherits from a base class, and then another class inherits from that derived class. This creates a "grandparent-parent-child" relationship.
Let's model a simple technology hierarchy.
Python
# Grandparent class
class Electronics:
def __init__(self):
self.type = "Electronic Device"
def has_power(self):
print("This device needs power.")
# Parent class (inherits from Electronics)
class Phone(Electronics):
def __init__(self):
super().__init__() # Call parent's init
self.type = "Phone"
def can_call(self):
print("This device can make calls.")
# Child class (inherits from Phone)
class SmartPhone(Phone):
def __init__(self):
super().__init__() # Call parent's init
self.type = "SmartPhone"
def has_internet(self):
print("This device can connect to the internet.")
# Create an object of the Child class
my_phone = SmartPhone()
# It has access to ALL ancestor methods
print(f"Type: {my_phone.type}")
my_phone.has_power() # From Electronics
my_phone.can_call() # From Phone
my_phone.has_internet() # From SmartPhone
Output:
Type: SmartPhone
This device needs power.
This device can make calls.
This device can connect to the internet.
The SmartPhone object can access methods from all its ancestors: Phone and Electronics. This is a very common pattern among the types of inheritance in Python.
This is used when you have a logical hierarchy of specialization.
Also Read: Understanding the Differences Between Inheritance and Polymorphism in Java
Hierarchical inheritance is the opposite of multiple inheritance. In this pattern, one parent class serves as the base for multiple child classes. This is one of the most widely used types of inheritance in Python for structuring an application.
Think of a base Account in a banking system.
Python
# Parent class
class Account:
def __init__(self, owner, balance):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount
print(f"Deposited {amount}. New balance: {self.balance}")
def withdraw(self, amount):
if amount > self.balance:
print("Insufficient funds.")
else:
self.balance -= amount
print(f"Withdrew {amount}. New balance: {self.balance}")
# Child class 1
class SavingsAccount(Account):
def __init__(self, owner, balance, interest_rate):
super().__init__(owner, balance)
self.interest_rate = interest_rate
def add_interest(self):
interest = self.balance * self.interest_rate
self.deposit(interest) # Reusing parent's method
print("Interest added.")
# Child class 2
class CheckingAccount(Account):
def __init__(self, owner, balance, overdraft_limit):
super().__init__(owner, balance)
self.overdraft_limit = overdraft_limit
# Overriding the withdraw method
def withdraw(self, amount):
if amount > (self.balance + self.overdraft_limit):
print("Overdraft limit exceeded.")
else:
self.balance -= amount
print(f"Withdrew {amount} (using overdraft). New balance: {self.balance}")
s_acct = SavingsAccount("Alice", 1000, 0.05)
c_acct = CheckingAccount("Bob", 500, 200)
s_acct.add_interest()
c_acct.withdraw(600)
Output:
Deposited 50.0. New balance: 1050.0
Interest added.
Withdrew 600 (using overdraft). New balance: -100
This pattern is perfect when you have a general category (Parent) and several specific "types" (Children) that share common logic but also have unique behaviors.
| Parent Class | Child Classes |
| Shape | Circle, Rectangle, Triangle |
| Employee | Manager, Developer, SalesPerson |
| Vehicle | Car, Truck, Motorcycle |
Also Read: Top Python Automation Projects & Topics For Beginners
Hybrid inheritance is exactly what it sounds like: a combination of two or more of the other types of inheritance in Python. For example, you might combine multilevel and multiple inheritance, or hierarchical and multilevel. These are common in complex, real-world models.
The most famous (or infamous) example of hybrid inheritance leads to the Diamond Problem.
Python
class A:
def ping(self):
print("Ping from A")
class B(A):
def ping(self):
print("Ping from B")
class C(A):
def ping(self):
print("Ping from C")
# D inherits from both B and C
class D(B, C):
pass
obj = D()
obj.ping()
This structure is a hybrid. It's Hierarchical (A is the parent for B and C) and also Multiple (D inherits from B and C).
The "Diamond Problem" is: When obj.ping() is called, which ping method should it run? A's, B's, or C's?
Python's Method Resolution Order (MRO) solves this unambiguously. Let's print the MRO for class D.
Python
print(D.__mro__)
Output:
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
Therefore, the output of obj.ping() is:
Ping from B
The MRO states the lookup order is D -> B -> C -> A.
Python's C3 linearization algorithm ensures a consistent, predictable order that respects inheritance hierarchy and avoids ambiguity. This makes even complex types of inheritance in Python with example scenarios like this manageable.
Also Read: Top 40 Pattern Programs in Python to Master Loops and Recursion
Inheritance isn't just a technical feature; it's a fundamental design strategy. Using it effectively can dramatically improve the quality of your code.
| Pros | Cons |
| Code Reusability: Enforces the DRY principle. | High Coupling: Child classes are tightly bound to their parent's implementation. A change in the parent can break the child. |
| Polymorphism: Allows for flexible and dynamic code. | Complexity: Deep (multilevel) or wide (multiple) inheritance can make code hard to read and debug (e.g., the Diamond Problem). |
| Logical Structure: Creates a clear "is-a" hierarchy. | Fragile Base Class: The "fragile base class problem" occurs when minor changes to the base class unexpectedly break child classes. |
| Extensibility: Easy to add new functionality by creating a new child class. | Overuse: Developers sometimes use inheritance when composition (the "has-a" relationship) would be a better, more flexible choice. |
Also Read: Enhance Your Python Skills: 10 Python Projects You Need to Try!
Let's see how these types of inheritance in Python are used in practice.
You have a main Player class, but different character types.
Python
class Player:
def __init__(self, name, level):
self.name = name
self.level = level
def attack(self):
print(f"{self.name} attacks!")
class Warrior(Player):
def __init__(self, name, level, weapon):
super().__init__(name, level)
self.weapon = weapon
def attack(self): # Overridden method
print(f"{self.name} swings a {self.weapon}!")
class Mage(Player):
def __init__(self, name, level, spell):
super().__init__(name, level)
self.spell = spell
def attack(self): # Overridden method
print(f"{self.name} casts {self.spell}!")
conan = Warrior("Conan", 10, "Greatsword")
gandalf = Mage("Gandalf", 20, "Fireball")
conan.attack()
gandalf.attack()
Output:
Conan swings a Greatsword!
Gandalf casts Fireball!
In a web framework like Django or Flask, you might model user permissions.
Python
class User:
def __init__(self, username):
self.username = username
def can_view_content(self):
return True
class Admin(User):
def can_edit_content(self):
return True
class SuperAdmin(Admin):
def can_delete_users(self):
return True
# A SuperAdmin has all capabilities
su = SuperAdmin("super_user")
print(f"View: {su.can_view_content()}")
print(f"Edit: {su.can_edit_content()}")
print(f"Delete: {su.can_delete_users()}")
Output:
View: True
Edit: True
Delete: True
In libraries like scikit-learn, models often inherit from a base estimator. This is a powerful use of this type of inheritance in Python.
Python
class BaseModel:
def fit(self, X, y):
print("Fitting the base model...")
# Common logic for all models
self._validate_data(X, y)
def predict(self, X):
raise NotImplementedError("Subclass must implement this.")
def _validate_data(self, X, y):
print("Validating data...")
class LinearRegression(BaseModel):
def fit(self, X, y):
super().fit(X, y) # Call parent's validation
print("Fitting Linear Regression model...")
def predict(self, X):
print("Predicting with Linear Regression...")
return [0] * len(X) # Dummy prediction
lr = LinearRegression()
lr.fit(X=[1,2,3], y=[1,2,3])
Output:
Fitting the base model...
Validating data...
Fitting Linear Regression model...
Also Read: Top 36+ Python Projects for Beginners and Students to Explore in 2025
This is the most important design decision related to all types of inheritance in Python.
| Feature | Inheritance ("is-a") | Composition ("has-a") |
| Relationship | class Child(Parent): | class Owner: def __init__(self): self.item = Item() |
| Coupling | Tight Coupling. Child is bound to parent's implementation. | Loose Coupling. Owner just knows the interface of the item, not its implementation. |
| Flexibility | Less Flexible. Set at compile time. Hard to change at runtime. | Very Flexible. Can change the item object at runtime to a different one. |
| Code Use | Inherits all parent methods (even ones you don't want). | Uses only the methods of the item that it explicitly calls. |
| Example | ElectricCar is-a Car. | Car has-a Engine. |
Example of Composition
Instead of inheriting, the Car contains an Engine object.
Python
class Engine:
def start(self):
print("Engine roars to life!")
def stop(self):
print("Engine sputters to a halt.")
class Car:
def __init__(self, make, model):
self.make = make
self.model = model
# COMPOSITION: The Car "has-a" Engine
self.engine = Engine()
def start_car(self):
print(f"Starting the {self.make} {self.model}...")
# It delegates the "start" work to the engine object
self.engine.start()
def stop_car(self):
self.engine.stop()
# The Car class is not an Engine, it USES an Engine.
my_car = Car("Ford", "Mustang")
my_car.start_car()
Output:
Starting the Ford Mustang...
Engine roars to life!
Also Read: Python AI Projects: Best 30 Artificial Intelligence Projects
To master the 5 types of inheritance in Python, start by practicing single-level inheritance for simplicity and gradually explore multi-level and multiple inheritance. Experiment with examples to understand method resolution order and hierarchy. This hands-on approach will solidify your understanding and make you proficient.
Many learners struggle to grasp inheritance complexities on their own. upGrad’s Python courses provide expert-led guidance and practical projects, helping you master inheritance concepts and advance your coding skills.
Here are some relevant courses to enhance your learning journey:
You can also get personalized career counseling with upGrad to guide your career path, or visit your nearest upGrad center and start hands-on training today!
Subscribe to upGrad's Newsletter
Join thousands of learners who receive useful tips
Unlock the power of data with our popular Data Science courses, designed to make you proficient in analytics, machine learning, and big data!
Elevate your career by learning essential Data Science skills such as statistical modeling, big data processing, predictive analytics, and SQL!
Stay informed and inspired with our popular Data Science articles, offering expert insights, trends, and practical tips for aspiring data professionals!
The five types of inheritance in Python are: Single (one parent, one child), Multiple (multiple parents, one child), Multilevel (a chain of inheritance), Hierarchical (one parent, multiple children), and Hybrid (a combination of any of the other types).
Single inheritance is the simplest type of inheritance in Python, where a child class derives from only one parent class. It's used to create a specialized version of a class, like class Dog(Animal):.
Multiple inheritance allows a child class to inherit from two or more parent classes, like class Child(Father, Mother):. Python uses the Method Resolution Order (MRO) algorithm to determine which parent's method to call if there's a name conflict.
Multilevel inheritance is a chain (A -> B -> C), creating a deep hierarchy. Hierarchical inheritance is a tree (A -> B, A -> C), where one parent has many children, creating a wide hierarchy.
Hybrid inheritance is a mix of any two or more types of inheritance in Python. The "diamond problem" (where a class inherits from two parents that share a common grandparent) is a classic example of hybrid inheritance.
Yes. This is called multiple inheritance, one of the main types of inheritance in Python. You list the parents in parentheses, like class MyClass(Parent1, Parent2):.
super() does not just call the parent. It calls the next method in the class's Method Resolution Order (MRO). This is crucial for making complex inheritance patterns, like multiple inheritance, work correctly.
MRO stands for Method Resolution Order. It's the algorithm (C3 linearization) Python uses to define the order in which to search for a method in a class's hierarchy. You can view it with ClassName.__mro__.
Python's MRO automatically solves the diamond problem by creating a consistent, predictable lookup path. You don't need to "avoid" it; you just need to understand the MRO to know which method will be called.
The main advantages are code reusability (DRY principle), polymorphism (treating child objects as parent objects), and creating a logical, maintainable structure for your code.
Inheritance creates tight coupling between classes; a change in the parent can break child classes. Deep or multiple inheritance can become very complex and hard to debug. Composition is often a more flexible alternative.
Yes. If a child class doesn't define its own __init__, the parent's __init__ is called automatically. If the child does define __init__, it must explicitly call super().__init__(...) to initialize the parent.
Inheritance is an "is-a" relationship (Dog is-a Animal). Composition is a "has-a" relationship (Car has-a Engine). Favoring composition over inheritance generally leads to more flexible and maintainable code.
By placing common code (attributes and methods) in a parent class, all child classes automatically get that functionality. You write the code once and reuse it everywhere, which is central to all types of inheritance in Python.
You should not use inheritance when a "has-a" relationship (composition) is more appropriate. If the child class doesn't need all of the parent's functionality or doesn't pass the "is-a" test, use composition instead.
Yes. This is a core feature of inheritance, known as method overriding. You simply define a method in the child class with the same name as the parent's method. This allows the child class to provide a specialized implementation.
The __init__ method is the constructor. In inheritance, the child's __init__ should call super().__init__() to ensure the parent's part of the object is correctly initialized before the child adds its own attributes.
Inheritance is the mechanism that enables polymorphism. Because a Dog is-an Animal, you can have a list of different Animal objects (Dog, Cat, Bird) and call the speak() method on each, getting a different result.
Technically, no. Python uses "name mangling" to make private members unique to their class (e.g., _ClassName__private). This means they are not directly accessible or overridden by child classes, which enforces encapsulation.
GUI toolkits (e.g., BaseWidget -> Button, TextBox). Web frameworks (e.g., BaseView -> UserView, AdminView). The Exception hierarchy in Python (e.g., Exception -> ValueError -> KeyError) is a perfect example of multilevel inheritance.
Reference Link:
https://python-course.eu/oop/inheritance.php
840 articles published
Rohit Sharma is the Head of Revenue & Programs (International), with over 8 years of experience in business analytics, EdTech, and program management. He holds an M.Tech from IIT Delhi and specializes...
Speak with Data Science Expert
By submitting, I accept the T&C and
Privacy Policy
Start Your Career in Data Science Today
Top Resources