Inheritance is the key principle of Object Oriented Programming. Inheritance is a feature that enables us to establish a hierarchy of classes, allowing them to share common properties and methods by deriving one class from another. It gives ability to a class to inherit or acquire the attributes and behaviors of another class.
Inheritance in Python
Inheritance in Python allows one class (called the child class or subclass) to inherit attributes and methods from another class (called the parent class or superclass). This promotes code reuse and enables hierarchical relationships between classes. The advantages of inheritance in Python are:
- Inheritance helps to accurately models real-world relationships.
- Inheritance promotes code reusability, allowing us to avoid duplicating code. Additionally, it makes it easier to extend a class with new features without altering its existing code.
- Inheritance is transitive, meaning if class B inherits from class A, all subclasses of B will also inherit from A.
- It provides a clear and intuitive class structure.
- Inheritance reduces development and maintenance costs by simplifying code management.
Syntax for inheritance in Python:
Class Parent
"""Parent class documentation string is optional"""
parent_class_attributes
class Child(Parent):
"""Child class documentation string is optional"""
child_class_attributes
In this, Child
is the child class which inherits from Parent
class.
Python supports multiple types of inheritance:
- Single Inheritance
- Multiple Inheritance
- Multilevel Inheritance
- Hierarchical Inheritance
- Hybrid Inheritance
Single Inheritance
As single inheritance a child class inherits from a single parent class. Let’s understand this with Parent class and Child class structure.
Parent Class Definition
# Definition of parent class
class Parent:
"""Parent class docstring"""
# __init__() is the constructor of the class
def __init__(self): # Initialize Parent class
print("inside Parent class constructor")
def parentClassMethod(self): # method in Parent class
print("inside Parent class method")
parent1 = Parent() # create an object of Parent Class
parent1.parentClassMethod() # call Parent class method using Parent class object
Child Class Inherit Parent Class
# Definition of child class
class Child(Parent): # Child class inherit Parent class
"""Child"""
# __init__() is the constructor of the class
def __init__(self): # Initialize Child class
print("inside Child class constructor")
def childClassMethod(self): # method in Child class
print("inside Child class method")
# create object & instance of Child class, with instance referring to object
child1 = Child() # create an object of Child Class
child1.childClassMethod() # call Child class method using Child class object
child1.parentClassMethod() # call Parent class method using Child class object
Child
class inheritsParent
class- Using
child1.parentClassMethod()
, we can callParent
class method usingChild
class object
try:
parent1.childClassMethod() # Using the Parent class, we cannot call Child class method
except AttributeError as err:
print("error", err)
# check for subclass (child class) of a superclass (parent class)
print("check for subclass (child class) of a superclass (parent class)")
print("Child class is sub class of Parent - ", issubclass(Child, Parent)) # Output => True
print("Parent class is sub class of Child - ", issubclass(Parent, Child)) # Output => False
# check for object is instance of given class
print("check for object is instance of given class")
print("child1 is instance of Child class - ", isinstance(child1, Child)) # Output => True
print("child1 is instance of Parent class - ", isinstance(child1, Parent)) # Output => True
print("parent1 is instance of Child class - ", isinstance(parent1, Child)) # Output => False
print("parent1 is instance of Parent class - ", isinstance(parent1, Parent)) # Output => True
parent1.childClassMethod()
=> we cannot callChild
class methods usingParent
class object.issubclass(Child, Parent)
=>Child
class is a subclass ofParent
class. returnsTrue
.isinstance(child1, Child)
andisinstance(child1, Parent)
=> both returnsTrue
.child1
is an object ofChild
class which inheritsParent
class. So,child1
is also an object ofParent
class.
Practical Example of Single Inheritance
# Parent class
class Shbytes:
def company_info(self):
print("Shbytes is a platform for learning tech skills.")
# Child class inheriting from Shbytes
class Courses(Shbytes):
def display_course(self):
print("We offer courses on Python, Data Science, and AI.")
# Create an object of the child class
course = Courses()
# Calling method from the parent class
course.company_info() # Output => Shbytes is a platform for learning tech skills.
# Calling method from the child class
course.display_course() # Output => We offer courses on Python, Data Science, and AI.
- The
Shbytes
class contains acompany_info()
method. - The
Courses
class inherits fromShbytes
and adds adisplay_course()
method. - The child class
Courses
has access to thecompany_info()
method from the parent class.
Multiple Inheritance
The child class inherits from more than one parent class.
# Definition of Parent1 class
print("Definition of parent class")
class Parent1:
def parent1_method(self):
print("inside Parent1 class method")
# Definition of Parent2 class
class Parent2:
def parent2_method(self):
print("inside Parent2 class method")
# Definition of Child class which inherits Parent1 and Parent2 class
print("Definition of child class")
class Child(Parent1, Parent2):
def child_method(self):
print("inside Child class method")
# create object & instance of the class, with instance referring to object
print("create object & instance of the class, with instance referring to object")
child1 = Child()
child1.child_method() # Child class object access Child class method
child1.parent1_method() # Child class object access Parent1 class method
child1.parent2_method() # Child class object access Parent2 class method
- The
Parent1
class contains aparent1_method()
method. - The
Parent2
class contains aparent2_method()
method. - The
Child
class inherits from bothParent1
andParent2
classes.Child
class has its own methodchild_method()
. - The child class
Child
has access to theparent1_method()
method from theParent1
class andparent2_method()
method from theParent2
class.
Practical Example of Multiple Inheritance
# Parent Class 1
class Shbytes:
def company_info(self):
print("Shbytes is an EdTech company providing IT solutions and training.")
# Parent Class 2
class Courses:
def course_info(self):
print("Shbytes offers courses in Python, Data Science, and Cloud Computing.")
# Child Class inheriting from both Shbytes and Courses
class Training(Shbytes, Courses):
def training_details(self):
print("The training includes hands-on labs and real-world projects.")
# Creating an object of the Training class
training_session = Training()
# Accessing methods from parent classes and the child class
training_session.company_info() # Method from Shbytes class
training_session.course_info() # Method from Courses class
training_session.training_details() # Method from Training class
- The
Shbytes
class contains acompany_info()
method. - The
Courses
class contains acourse_info()
method. - The
Training
class inherits from bothShbytes
andCourses
, and it adds its owntraining_details()
method. - We can access methods from all three classes using
Training
class objecttraining_session
.
Program Output
Shbytes is an EdTech company providing IT solutions and training.
Shbytes offers courses in Python, Data Science, and Cloud Computing.
The training includes hands-on labs and real-world projects.
Multilevel Inheritance
In multilevel inheritance, class inheritance is in multiple levels. The child class inherits from a parent class, which itself is a child of another class. Ex. Child
class inherits from Parent
class and Parent
class itself inherits from GrandParent
class.
# Definition of GrandParent class
class GrandParent:
def grand_parent_method(self):
print("inside GrandParent class method")
# Definition of Parent class inherits GrandParent class
class Parent(GrandParent):
def parent_method(self):
print("inside Parent class method")
# Definition of Child class inherits Parent class
class Child(Parent):
def child_method(self):
print("inside Child class method")
# create object & instance of the class, with instance referring to object
print("create object & instance of the class, with instance referring to object")
child1 = Child()
child1.child_method() # Child class object access Child class method
child1.parent_method() # Child class object access Parent class method
child1.grand_parent_method() # Child class object access GrandParent class method
parent1 = Parent()
parent1.parent_method() # Parent class object access Parent class method
parent1.grand_parent_method() # Parent class object access GrandParent class method
- The
GrandParent
class contains agrand_parent_method()
method. - The
Parent
class inheritsGrandParent
class and contains aparent_method()
method. Because of inheritance,Parent
class object will also have access togrand_parent_method()
. - The
Child
class inheritsParent
class and added its own methodchild_method()
. - Because of multilevel inheritance,
Child
class object has access to theparent_method()
method from theParent
class andgrand_parent_method()
method fromGrandParent
class.
Practical Example of Multilevel Inheritance
# GrandParent class
class Shbytes:
def company_info(self):
print("Shbytes: A platform for educational courses.")
# Parent class (inherits from Shbytes)
class Courses(Shbytes):
def course_info(self):
print("Courses: Offering a variety of tech and business courses.")
# Child class (inherits from Courses)
class PythonCourse(Courses):
def python_course_info(self):
print("Python Course: A detailed course on Python programming.")
# Creating an object of the grandchild class
python_course = PythonCourse()
# Calling methods from all levels of inheritance
python_course.company_info() # Inherited from Shbytes (GrandParent class)
python_course.course_info() # Inherited from Courses (Parent class)
python_course.python_course_info() # Method of PythonCourse (Child class)
- The
Shbytes
class contains a methodcompany_info()
. - The
Courses
class inherits fromShbytes
and adds its own methodcourse_info()
. - The
PythonCourse
class, which inherits fromCourses
, adds its own methodpython_course_info()
. PythonCourse
class object will have access to methods fromCourses
class andShbytes
class.
Program Output
Shbytes: A platform for educational courses.
Courses: Offering a variety of tech and business courses.
Python Course: A detailed course on Python programming.
Hierarchical Inheritance
In hierarchical inheritance, multiple child classes inherit from the same parent class. Example FirstChild
and SecondChild
both classes inherits from Parent
class.
# Definition of Parent class
class Parent():
def parent_method(self):
print("inside Parent class method")
# Definition of FirstChild class inherits Parent class
class FirstChild(Parent):
def first_child_method(self):
print("inside FirstChild class method")
# Definition of SecondChild class inherits Parent class
class SecondChild(Parent):
def second_child_method(self):
print("inside SecondChild class method")
# create object & instance of the class, with instance referring to object
print("create object & instance of the class, with instance referring to object")
first_child = FirstChild()
first_child.first_child_method() # FirstChild class object access FirstChild class method
first_child.parent_method() # FirstChild class object access Parent class method
second_child = SecondChild()
second_child.second_child_method() # SecondChild class object access SecondChild class method
second_child.parent_method() # SecondChild class object access Parent class method
- The
Parent
class contains aparent_method()
method. - The
FirstChild
class inheritsParent
class and containsfirst_child_method()
method. - The
SecondChild
class inheritsParent
class and containssecond_child_method()
method. - Because of hierarchical inheritance,
FirstChild
andSecondChild
class objects will have access toparent_method()
from theParent
class.
first_child.second_child_method()
#FirstChild
class object cannot accessSecondChild
class methodsecond_child.first_child_method()
#SecondChild
class object cannot accessFirstChild
class method
Practical Example of Hierarchical Inheritance
# Parent class
class Shbytes:
def company_info(self):
print("Welcome to Shbytes - Learn Tech Skills for a Digital Future!")
# Child class 1
class PythonCourse(Shbytes): # Inherits from Shbytes
def course_details(self):
print("Course: Python Programming\nDuration: 8 Weeks")
# Child class 2
class PowerBICourse(Shbytes): # Inherits from Shbytes
def course_details(self):
print("Course: Power BI for Data Analysis\nDuration: 6 Weeks")
# Creating objects of child classes
python_course = PythonCourse()
powerbi_course = PowerBICourse()
# Calling methods
python_course.company_info() # Inherited from Shbytes
python_course.course_details() # Method from PythonCourse
print() # For readability
powerbi_course.company_info() # Inherited from Shbytes
powerbi_course.course_details() # Method from PowerBICourse
- The
Shbytes
class serves as the parent class, containing thecompany_info
method. - The
PythonCourse
andPowerBICourse
classes inherit fromShbytes
and have their owncourse_details
methods, representing different courses offered by Shbytes.
Program Output
Welcome to Shbytes - Learn Tech Skills for a Digital Future!
Course: Python Programming
Duration: 8 Weeks
Welcome to Shbytes - Learn Tech Skills for a Digital Future!
Course: Power BI for Data Analysis
Duration: 6 Weeks
Hybrid Inheritance
A combination of more than one type of inheritance e.g., a combination of multilevel and multiple inheritance OR multilevel and hierarchical inheritance.
# Definition of GrandParent class
class GrandParent:
def grand_parent_method(self):
print("inside GrandParent class method")
# Hierarchical Inheritance
# Definition of Parent1 class inherits GrandParent class
class Parent1(GrandParent):
def method1(self):
print("inside Parent1 class method")
# calling GrandParent method with Parent1 class or its Child class object
GrandParent.grand_parent_method(self)
# Hierarchical Inheritance
# Definition of Parent2 class inherits GrandParent class
class Parent2(GrandParent):
def method1(self):
print("inside Parent2 class method")
# calling GrandParent method with Parent2 class or its Child class object
GrandParent.grand_parent_method(self)
# Multiple Inheritance
# Definition of Child class inherits Parent1Level1 and Parent2Level1 class
class Child(Parent1, Parent2):
def child_method(self):
print("inside Child class method")
Parent1.method1(self) # calling Parent1 method with Child class object
Parent2.method1(self) # calling Parent2 method with Child class object
child = Child()
child.child_method()
- The
GrandParent
class containsgrand_parent_method()
method. - The
Parent1
class inheritsGrandParent
class and contains its ownmethod1()
method. Using inheritanceGrandParent.grand_parent_method(self)
makes a call toGrandParent
method withParent1
class OR its Child class objects. - The
Parent2
class inheritsGrandParent
class and contains its ownmethod1()
method. Using inheritanceGrandParent.grand_parent_method(self)
makes a call toGrandParent
method withParent2
class OR its Child class objects. - Because of hierarchical inheritance,
Parent1
andParent2
class objects will have access togrant_parent_method()
from theGrandParent
class. - The
Child
class inherits from bothParent1
andParent2
classes.Child
class has its own methodchild_method()
. - The
Child
class has access tomethod1()
from theParent1
class andmethod2()
from theParent2
class. It also has access togrant_parent_method()
from theGrandParent
class.
Practical Example of Hybrid Inheritance
# GrandParent Class
class Shbytes:
def __init__(self, institute_name):
self.institute_name = institute_name
def show_institute(self):
print(f"Institution: {self.institute_name}")
# First Course Class
class PythonCourse(Shbytes):
def __init__(self, institute_name, python_course_name):
super().__init__(self, institute_name)
self.python_course_name = python_course_name
def show_python_course(self):
print(f"Python Course: {self.python_course_name}")
# Second Course Class
class PowerBICourse(Shbytes):
def __init__(self, institute_name, powerbi_course_name):
super().__init__(institute_name)
self.powerbi_course_name = powerbi_course_name
def show_power_bi_course(self):
print(f"Power BI Course: {self.powerbi_course_name}")
# Child Class that inherits from both PythonCourse and PowerBICourse
class Training(PythonCourse, PowerBICourse):
def __init__(self, institute_name, python_course_name, power_bi_course_name, training_type):
# Call constructors of both parent classes
PythonCourse.__init__(self, institute_name, python_course_name)
PowerBICourse.__init__(self, institute_name, power_bi_course_name)
self.training_type = training_type
def show_training(self):
print(f"Training Type: {self.training_type}")
self.show_python_course()
self.show_power_bi_course()
# Creating an instance of the Training class
training = Training("Shbytes Academy", "Advanced Python", "Power BI Dashboards", "Online Training")
# Calling methods
training.show_institute() # Inherited from Shbytes
training.show_training() # Inherited from both PythonCourse and PowerBiCourse
- The
Shbytes
class serves as the parent class, containing the attributeinstitute_name
andshow_institute
method. - The
PythonCourse
andPowerBICourse
classes inherit fromShbytes
and have their own methods, representing different courses offered by Shbytes. Their__init__
method calls thesuper().__init__
method. Training
class inherits from bothPythonCourse
andPowerBICourse
classes.
super()
method
super()
method in Python is a built-in function that allows us to access methods from a parent or sibling class
. It’s mainly used in the context of inheritance, where we want to call a method of a parent class in a child class, ensuring that the child class extends or modifies the parent class functionality.
Why Use super()
?
- Avoids hardcoding parent class names – We don’t need to explicitly refer to the parent class by name, making our code more maintainable.
- Multiple inheritance support – In cases of multiple inheritance,
super()
handles method resolution correctly according to the Method Resolution Order (MRO). - Code reusability – It allows child classes to reuse the functionality of their parent classes without repeating code.
Syntax of super() method – super().method_name(arguments)
=> method_name
refers to the method in the parent class that we want to call, and arguments
are the parameters that the method accepts.
In our hybrid inheritance example, we called parent class __init__ method in two ways:
PythonCourse.__init__(self, institute_name, python_course_name)
=> This called the __init__ method of the given class name.super().__init__(self, institute_name)
=> Usingsuper()
method we called the parent class__init__
method. This approach is better approach, as we don’t need to remember the parent class name and we can reuse the code block.
Method Resolution Order (MRO)
The Method Resolution Order (MRO) is the order in which Python looks for methods when they are called using super()
. We can check the MRO of any class using the __mro__
attribute or the mro()
method.
ClassName.__mro__
=> Returns tuple of class method resolution orderClassName.mro()
=> Returns list of class method resolution order
From the hybrid inheritance example we can check for MRO of Training
class..
print(Training.__mro__) # Returns tuple of class method resolution order
print(Training.mro()) # Returns list of class method resolution order
# Output
# (<class '__main__.Training'>, <class '__main__.PythonCourse'>, <class '__main__.PowerBICourse'>, <class '__main__.Shbytes'>, <class 'object'>)
# [<class '__main__.Training'>, <class '__main__.PythonCourse'>, <class '__main__.PowerBICourse'>, <class '__main__.Shbytes'>, <class 'object'>]
super()
ensures that all classes in a hierarchy are properly initialized and called in the correct order, especially in the case of multiple inheritance.- It avoids to hardcode the parent class, leading to more maintainable and extendable code.
Summary
In this article, we learned about Object Oriented Programming – Inheritance in Python. Following topics were covered:
Code – Github Repository
All code snippets and programs for this article and for Python tutorial, can be accessed from Github repository – Comments and Docstring in Python.