Multiple Inheritance in Python

We offer you a brighter future with FREE online courses - Start Now!!

Unlike other languages, Python supports multiple inheritance. It is one of the five types of inheritance in Python. The ability of a class to inherit more than one class is called Multiple Inheritance.

Using multiple Inheritance, a subclass can have multiple superclasses. In this article, we will discuss how we can inherit multiple classes, what complications arise due to this, and how to deal with those complications.

 

How to Inherit Multiple classes?

In Python, inheriting a hundred classes is as easy as inheriting a single class. To inherit multiple classes, we use the following syntax.

Syntax of Multiple Inheritance in Python

class Subclass(Superclass1, Superclass2,..., SuperclassN):
   # Class body...

Using the above syntax, let’s create a class Child that inherits two classes Parent1 and Parent2.

class Parent1:
   pass

class Parent2:
   pass

class Child(Parent1, Parent2):
   pass

if issubclass(Child, (Parent1, Parent2)):
   print("Child is a subclass of Parent1 and Parent2")

Output

Child is a subclass of Parent1 and Parent2

In the above code, class Child inherits multiple classes Parent1 and Parent2.

A subclass can access all the attributes and methods of its superclasses. All the attributes and methods of a parent class can be accessed by a child class.

For Example:

class Parent1:

   def display1(self):
       print("In class Parent1")

class Parent2:

   def display2(self):
       print("In class Parent2")

class Child(Parent1, Parent2):
   pass

obj = Child()
obj.display1()
obj.display2()

Output

In class Parent1
In class Parent2

In the above code, the subclass Child accessed the methods of both Parent1 and Parent2 classes.

Complications of Multiple Inheritance in Python

Although multiple inheritance gives us the ability to create complex relationships, it also creates few complications. We can understand these complications with the help of a famous problem called the Diamond problem

The Diamond Problem in Python

Diamond Problem in Inheritance

Diamond problem is the uncertainty created when class Z inherits two subclasses X and Y of a superclass A.

Example of Python Diamond Problem

class A:
   pass
class X(A):
   pass
class Y(A):
   pass
class Z(X, Y):
   pass
print(issubclass(Z, (A,X,Y)))

Output

True

Since both classes X and Y inherited the same class A, all three classes A, X, Y have common methods and attributes. This won’t be a problem as long as we don’t override any method.

For Example

class A:
   def display(self):
       print("Class A")

class X(A):
   pass
class Y(A):
   pass
class Z(X, Y):
   pass

obj = Z()
obj.display()

Output

Class A

The issues arise as soon as we override the method. If we override the method in both classes X and Y, then from what class should class Z inherit the method? Let’s see with example below:

class A:

   def display(self):
       print("Class A")

class X(A):

   def display(self):
       print("Class X")

class Y(A):

   def display(self):
       print("Class Y")

class Z(X, Y):
   pass

obj = Z()
obj.display()

Output

Class X

In the above code example, class Z inherited the method from class X.

Similarly, if we override the method in only one class Y, then the question arises, whether class Z inherits the method from class X or class Y. Let’s see with an example:

class A:

   def display(self):
       print("Class A")

class X(A):
   pass

class Y(A):

   def display(self):
       print("Class Y")

class Z(X, Y):
   pass

obj = Z()
obj.display()

Output

Class Y

In the above code example, class Z inherited the method from Class Y.

To understand and solve these complications, we use the Method Resolution Order.

Method Resolution Order (MRO) in Python

Whenever we need to search an attribute or a method, Python follows a pre-defined order to search. According to the order, Python first searches in the current class. If not found, then it goes to the superclasses. It searches the superclasses in depth-first, left to right fashion. This order is known as the Linearization of the class subclass.

Python uses a set of rules to find this order, these rules are called Method Resolution Order.

For Example

class Parent1:

   def show(self):
       print("PythonGeeks")

class Parent2:

   def show(self):
       print("Hello World")

class Child(Parent1, Parent2):
   pass

geek = Child()
geek.show()

Output

PythonGeeks

In the above code example, the search order is Child, Parent1, Parent2, and object.

According to the order, Python first searched in the Child class. Since it is empty, Python went to parent classes. From left to right, Python first searched in Parent1 and found the method. So, Python stopped the search and executed the method.

Find MRO of a Class in Python

We can view the MRO of a class by using the attribute __mro__ or the method mro().

Syntax

class.mro()

Or

class.__mro__

For Example

print(f"MRO of Parent1 is {Parent1.mro()}")
print(f"MRO of Child is {Child.__mro__}")

Output

MRO of Parent1 is [<class ‘__main__.Parent1’>, <class ‘object’>]
MRO of Child is (<class ‘__main__.Child’>, <class ‘__main__.Parent1’>, <class ‘__main__.Parent2’>, <class ‘object’>)

In the above code example, we can see the MRO of classes Parent1 and Child.

Super() and its Uses in Python

Super() is a function that returns a temporary representation of a parent class.

This is one of the most useful functions while implementing Multiple Inheritance. Consider a scenario where all classes have the same method and we need to invoke all those methods exactly once directly from the subclass.

For Example

class A:
   def target(self):
   print("Invoked method in class A")

class B(A):
   def target(self):
   print("Invoked method in class B")

class C(A):
   def target(self):
   print("Invoked method in class C")

class D(B, C):
   def target(self):
   print("Invoked method in class D")
obj = D()
obj.target()

Output

Invoked method in class D

In the above code example, when we called the target(), only the child class’s method is invoked. Since the methods of the parent classes are overridden, we can not directly call those methods in classes A, B, and C.

One naive solution to directly call other methods from the subclass is placing method calls in every class.

For Example

class A:
   def target(self):
   print("Invoked method in class A")

class B(A):
   def target(self):
       print("Invoked method in class B")
       A.target(self)

class C(A):
   def target(self):
       print("Invoked method in class C")
       A.target(self)

class D(B, C):
   def target(self):
       print("Invoked method in class D")
       B.target(self)
       C.target(self)
obj = D()
obj.target()

Output

Invoked method in class D
Invoked method in class B
Invoked method in class A
Invoked method in class C
Invoked method in class A

Although this is simple, this is not efficient. It calls the same method twice.

We can use the super() function to solve this and get the correct output.

For Example

class A:
   def target(self):
   print("Invoked method in class A")

class B(A):
   def target(self):
       print("Invoked method in class B")
       super().target()

class C(A):
   def target(self):
       print("Invoked method in class C")
       super().target()

class D(B, C):
   def target(self):
       print("Invoked method in class D")
       super().target()
obj = D()
obj.target()

Output

Invoked method in class D
Invoked method in class B
Invoked method in class C
Invoked method in class A

In the above code example, super() does exactly what we intended to do. It invoked all the methods directly from the subclass without any duplication.

Multilevel Inheritance in Python

Multilevel Inheritance in Inheritance

Another type of inheritance that is similar to Multiple inheritance is Multi-level inheritance.

In multi-level inheritance, a class inherits a child class instead of a parent class. Since it inherits a child class, we can refer to it as a grandchild class.

Multi-level inheritance represents a parent-child-grandchild relationship.

Example of Multilevel Inheritance in Python

class Parent:
   pass
class Child(Parent):
   pass
class GrandChild(Child):
   pass
print(issubclass(GrandChild, (Child, Parent)))

Output

True

In the above code example, Child class inherited Parent class and GrandChild class inherited Child class.

GrandChild class is a subclass of both Child class and Parent class. The GrandChild class can access the attributes and methods of both the Child and Parent classes.

class Parent:
   def method1(self):
       print("Parent Class")
class Child(Parent):
   def method2(self):
       print("Child Class")
class GrandChild(Child):
   pass
obj = GrandChild()
obj.method1()
obj.method2()

Output

Parent Class
Child Class

In the above code example, GrandChild class accessed the methods of Child class and Parent class.

Python Multi-level Inheritance vs Multiple Inheritance

Multi-level Inheritance in Python Multiple Inheritance in Python
Simple to understand and implement Complex to understand and implement
It is used often It is rarely used
Supported by most languages Supported by only a few languages
Three levels of inheritance are required Only one level of inheritance is required
A subclass needs to inherit another subclass A subclass needs to inherit more than one superclass
It involves a parent class, a child class, and a grandchild class. It involves a minimum of two parent classes and one child class.

Advantages of Multiple Inheritance in Python

1. The main advantage of multiple inheritance is that it allows us to create complex relationships among classes.

2. Since the subclass inherits two or more superclasses, the subclass can have access to a wide variety of methods and attributes of its superclasses.

3. It enables us to organize classes and objects by classifying them into different categories.

4. It helps us to reuse the code and saves a lot of development time.

Disadvantages of Multiple Inheritance in Python

1. Many languages still do not support Multiple inheritance. 

2. If we want to port our code to a different language, we need to recode and change the entire model of our program. 

3. This makes porting incredibly difficult and time-consuming.

4. Inheriting multiple superclasses creates several problems and confusion. The Diamond problem is one such example. 

Real-life Examples of Multiple Inheritance

Multiple Inheritance excels in demonstrating collabs and mergers.

Do you remember the song Ice Cream, produced as a result of the collaboration between Blackpink and Selena Gomez? Multiple Inheritance can be used to demonstrate this collaboration. 

For Example

class Blackpink:
   name1 = "Blackpink"
class Selena:
   name2 = "Selena Gomez"
class IceCream(Blackpink, Selena):
   def artists(self):
   print(f"{self.name1} and {self.name2}")
song = IceCream()
song.artists()

Output

Blackpink and Selena Gomez

Since Ice cream is recorded by both Blackpink and Selena, it has both their characteristics.

The most recent and famous merger of Vodafone and Idea can be demonstrated by using Multiple Inheritance.

For Example

class Vodafone:
   subscribers1 = 200
class Idea:
   subscribers2 = 82
class Vi(Vodafone, Idea):
   def subscribers(self):
       print(f"Vi Subscribers = "
             f"{self.subscribers1 + self.subscribers2}"
             f" million")
company = Vi()
company.subscribers()

Output

Vi Subscribers = 282 million

The new company Vi has acquired/inherited both the Vodafone and Idea’s subscribers.

Similarly, it can also be used to store data, for example, students in a university.

Python Interview Questions on Multiple Inheritance

Q1. Create three empty classes Father, Mother, and Child. Child class should inherit the Father class and Mother class.

Ans 1. The Complete code is as follows:

class Father:
   pass

class Mother:
   pass

class Child(Father, Mother):
   pass

Q2. Complete the code by creating a subclass and a method to concatenate and return the string.

class Class1:

   str1 = "Hello"

class Class2:
   str2 = "World"

# Code here...


obj = Class3()
obj.get_str()

Ans 2. Complete code is as follows:

class Class1:
   str1 = "Hello "

class Class2:
   str2 = "World"

# Code here...
class Class3(Class1, Class2):
 
   def get_str(self):
       str3 = Class1.str1 + Class2.str2
       print(str3)

obj = Class3()
obj.get_str()

Output

Hello World

Q3. Create a class D which inherits class B and C. B and C inherit class A.

Ans 3. Complete code is as follows:

class A:
   pass

class B(A):
   pass

class C(A):
   pass

class D(B, C):
   pass

Q4. What is the output of the following code?

class Salt:
   name = "Salt"
class Water:
   name = "Water"
class SaltWater(Salt, Water):
   pass

water = SaltWater()
print(water.name)

Ans 4. The output of the given code is

Salt

Q5. What is the output of the following code?

class Desktop:  
   def details(self):
       print("This is a desktop computer")

class Laptop(Desktop):
   def details(self):
       print("This is a laptop")
      
class Tablet(Desktop):
   def details(self):
       print("This is a tablet")

class Phone(Laptop, Tablet):
   pass
phone = Phone()
phone.details()

Ans 5. The output of the given program is

This is a laptop

Quiz on Multiple Inheritance in Python

Conclusion

In this article, we discussed the way to implement multiple inheritance in Python. We learned about the problems created by multiple inheritance and how to solve them.

Furthermore, if you have any queries, please feel free to share them in the comments section.

Did we exceed your expectations?
If Yes, share your valuable feedback on Google | Facebook


2 Responses

  1. Voterak says:

    Quiz no 8 and 9 has wrong answers marked right. Kindly change it if you respect the quality of your site.

  2. anonym says:

    Questions 8 and 9 have wrong answers. Please correct them.

Leave a Reply

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