Multiple Inheritance in Python

This post is lesson 35 of 54 in the subject Python Programming Language

1. Multiple Inheritance in Python

A child class can inherit from more than one parent class. This is multiple inheritance. The child class inherits all attributes and methods of all classes.

class Base1:
  pass

class Base2:
  pass

class MultiDerived(Base1, Base2):
  pass
Multiple Inheritance in Python
Multiple Inheritance in Python
class Person:
  def info(self):
    print("Info of a person.")

class Employee:
  def showSalary(self):
    print("Salary of an employee.")

class Teacher(Person, Employee):
  pass

john = Teacher()
john.info()
john.showSalary()

Result

Info of a person.
Salary of an employee.

The Teacher class inherits from the Person and Employee classes in the above example. The Teacher class will inherit and use the info() and showSalary() methods from the above 2 classes.

2. Method Resolution Order (MRO) in Python

In some cases, parent classes may have methods with identical names. When a child class calls these methods, it is unclear which parent class method will be executed.

Method Resolution Order (MRO) in Python
Method Resolution Order (MRO) in Python

Python uses the Method Resolution Order (MRO) to determine which method is called in this case. MRO specifies one order in which class is prioritized to find and call the method first. We can use the __mro__ attribute or the mro() function to see this order.

class Person:
  def info(self):
    print("Info of a person.")
  def work(self):
    print("A person works.")

class Employee:
  def work(self):
    print("An employee works.")
  def showSalary(self):
    print("Salary of an employee.")

class Teacher(Person, Employee):
  pass

print(Teacher.__mro__)
john = Teacher()
john.work()

Result

(<class '__main__.Teacher'>, <class '__main__.Person'>, <class '__main__.Employee'>, <class 'object'>)
A person works.

In the above example, the Person class is prioritized to find the work() method to execute first due to the inheritance order class Teacher(Person, Employee).

class Person:
  def info(self):
    print("Info of a person.")
  def work(self):
    print("A person works.")

class Employee:
  def work(self):
    print("An employee works.")
  def showSalary(self):
    print("Salary of an employee.")

class Teacher(Employee, Person):
  pass

print(Teacher.mro())
john = Teacher()
john.work()

Result

(<class '__main__.Teacher'>, <class '__main__.Employee'>, <class '__main__.Person'>, <class 'object'>)
An employee works.

In the above example, the Employee class is prioritized to find the work() method to execute first due to the inheritance order class Teacher(Employee, Person).

Note: All classes created in Python automatically inherit from the object class.

3. Multilevel Inheritance in Python

We can also create a new class by inheriting from a child class. This is multilevel inheritance. Python has no limit on the number of levels of inheritance.

Multilevel Inheritance in Python
Multilevel Inheritance in Python

In multilevel inheritance, the new child class inherits all the attributes and methods of both the parent and child classes.

class Base:
  def methodBase(self):
    print("This is a method of Base.")

class Derived1(Base):
  def methodDerived1(self):
    print("This is a method of Derived1.")

class Derived2(Derived1):
  def methodDerived2(self):
    print("This is a method of Derived2.")

# create an object of Derived2
obj = Derived2()
# call method inherits from Base
obj.methodBase()
# call method inherits from Derived1
obj.methodDerived1()
# call method of Derived2
obj.methodDerived2()

Result

This is a method of Base.
This is a method of Derived1.
This is a method of Derived2.

In the above example, the Derived1 class inherits from the Base class. The Derived2 class inherits from the Derived1 class. The Derived2 class will inherit all the attributes and methods of the Base and Derived1 classes.

4. The init() Function in Multiple Inheritance

In multiple inheritances in Python, the child class will inherit the __init__() function of the parent classes. When creating an object of the child class, which __init__() function will be called? As we know, Python uses the Method Resolution Order (MRO) to solve this problem. But then, there is an issue. Let’s see the following example to see this problem.

class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age
  def info(self):
    print(self.name + ",", self.age, "years old.")

class Employee:
  def __init__(self, salary):
    self.salary = salary

  def showSalary(self):
    print("salary:", self.salary)

class Teacher(Person, Employee):
  pass

print(Teacher.mro())
john = Teacher("John", 35)
# call method inherits from Person
john.info()
# AttributeError: 'Teacher' object has no attribute 'salary'
john.showSalary()

Result

[<class '__main__.Teacher'>, <class '__main__.Person'>, <class '__main__.Employee'>, <class 'object'>]
John, 35 years old.
Traceback (most recent call last):
  File "c:\python-examples\main.py", line 20, in <module>
    john.showSalary()
  File "c:\python-examples\main.py", line 13, in showSalary
    print("salary:", self.salary)
AttributeError: 'Teacher' object has no attribute 'salary'

The issue here is that the __init__() function used to create an object of the Teacher class is inherited from the Person class. Currently, the object has only inherited the attributes of “name” and “age” from the “Person” class. It does not have the “salary” attribute from the “Employee” class. The solution in such cases is to define the __init__() function of the Teacher class.

class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age
  def info(self):
    print(self.name + ",", self.age, "years old.")

class Employee:
  def __init__(self, salary):
    self.salary = salary

  def showSalary(self):
    print("salary:", self.salary)

class Teacher(Person, Employee):
  def __init__(self, name, age, salary):
    super().__init__(name, age)
    self.salary = salary

# create an object of Teacher with it's __init__() function
john = Teacher("John", 35, "5000000")
# call method inherits from Person
john.info()
# call method inherits from Employee
john.showSalary()

Result

John, 35 years old.
salary: 5000000

In the above example, we use the statement super().__init__(name, age) to call the initializer of the Person class. Then, we add the salary attribute to the Teacher objects.

5/5 - (1 vote)
Previous and next lesson in subject<< Inheritance in PythonEncapsulation and Polymorphism in Python >>

Leave a Reply

Your email address will not be published. Required fields are marked *