How to Use Multiple Inheritance in Python

R. Parker
The KickStarter
Published in
6 min readJul 1, 2020

An introductory guide to multiple inheritance and the diamond problem in python.

Photo by Christina Morillo from Pexels

Hi Python folks, I decided to start a new series that focuses on Python. I work with Python daily and through the impact of Machine Learning, it gained a lot of momentum in the past years. I also learned Python to build and train machine learning models and then, later on, I started to learn the more advanced concepts in Python.

Today I will focus on multiple inheritance, the super() function, and how to tackle the diamond problem.

Multiple Inheritance is a controversial topic, often it is considered to be a ‘bad practice’ since most programming languages only provide poor implementation mechanisms. Common languages such as Java don’t provide the option at all, while Python has a sophisticated and well-designed approach to multiple inheritance.

If you are already familiar with Inheritance itself, feel free to skip the next paragraph and start by revising the importance of the super function.

What is Inheritance?

Inheritance allows us to create a new class that inherits methods and properties from another class. The other class is usually referred to as parent class, or base class, while the class that inherits from the parent class is called child class or derived class.

Example of Inheritance in Python

Let’s have a look at inheritance in Python. In our example, we have a parent class Person and our child class Employee.

The parent class has properties such as the age and name of a person and two methods to return those.

The child class inherits those properties and also adds Employee specific ones, such as the employee id.

To define the relation to the parent class one has to mention the parent class name in the input parameter of the child class (See line 15).

We initialize the class Person in line 17 during the initialization of the class Employee. Therefore, we start by passing all arguments to class Employee (line 24), which then initializes the Employee and Person class.

Compiling the program outputs shows us that we successfully accessed the properties and methods of the class Person:

Peter
13823412

What are the advantages of Inheritance?

  • We represent relationships as they exist in the real-world
  • Inheritance allows the reusability of code, as we can leverage already implemented properties of a parent class.

The super() function

I know you opened this article to learn about Multiple Inheritance and we will get there in a minute, but before, it is crucial to understand the benefits of the super function in Python.

You remember the part when we initialized the parent class in the Employee class? Well, there is an alternative to do that with the super function:

Before: Person.__init__(self, name, age)
Alternative: super().__init__(name, age)

Do you see the difference? There is no need to explicitly state which parent class we want to initialize. We avoid using the base class name explicitly. If you are inheriting from one parent class the benefit seems negligible, once you start working with multiple parent classes you will understand the benefit of initializing them all together.

Multiple Inheritance

The idea if multiple inheritance is easily explained; a class can inherit attributes and methods from more than one parent class.

In this example, the Child class can access the attributes and methods from the parent classes A, B, and C.

Example of Multiple Inheritance in Python
Output:
This is class 1
This is class 2

The class ‘ClassOverview’ inherits the methods of both parent classes since they are passed as arguments to the class. Calling the methods works fine and we create the expected output by calling the parent methods.

This seems to be straightforward so far, but what happens if both parent classes have a method with the same name? Which one should we prefer?

This is when the Method Resolution Order (MRO) comes into play. MRO is the order in which Python looks for a method in a hierarchy of classes.

print(classes.__class__.__mro__)(<class '__main__.ClassOverview'>, <class '__main__.Class1'>, <class '__main__.Class2'>, <class 'object'>)

You can simply access the Resolution Order as shown above and we can see that Python looks first at the class ClassOverView, second at Class1, then Class 2, and finally at the object class, which is a superclass for all classes. This means if class 1 and class 2 share a method with the same name we use the one of class 1 since it’s passed in the definition of ClassOverview before Class 2.

The Diamond Problem and Super

The diamond problem is not exclusive to Python, it can arise when two classes (class 2 and 3) inherit from class 1 and subsequently, class 4 inherits from both, class 2 and class 3.

This combination so far is not a problem and is common.

The problem arises if class 2 or 3 (or even both) override a method from their parent class. This provides two different methods with the same name to class 4 and a decision has to be made which one to inherit.

Multiple Inheritance in Python — Diamond Problem without super()

In the example above, both class B and class C override the help method of class A. Calling the method help on an instance of class D would return ‘Class B called for help’ following the Method Resolution Order.

How can we work around this issue and know which classes called for help? We could start calling the parent methods in class B and class C as well and also make sure to explicitly call both in class D!

Multiple Inheritance in Python — Workaround of Diamond Problem without super()

Calling the method help on class D now returns the following:

Class B called for help
Class A called for help
Class C called for help
Class A called for help

Well, we called method help from class A twice, therefore the output should not surprise us. However, it’s not really what we want, we only want to call it once.

The pythonic way to solve this issue is by using the super function:

Multiple Inheritance in Python with super() function

We replaced the explicit call of the method from the parent class with the super() function. Super() delegates method calls to classes in the instance’s ancestor tree. Hereby it avoids initializing a class multiple times. This leads to the desired output:

Class B called for help
Class C called for help
Class A called for help

This use case is unique to Python and is not found in statically compiled languages or languages that only support single inheritance. This makes it possible to implement “diamond diagrams” where multiple base classes implement the same method. Good design dictates that this method have the same calling signature in every case (because the order of calls is determined at runtime, because that order adapts to changes in the class hierarchy, and because that order can include sibling classes that are unknown prior to runtime).

Today you learned the following:

  • How Inheritance works and its advantages
  • Multiple Inheritance in Python
  • The diamond problem and how to resolve it through the help of super()

If you are still facing trouble understanding the topics please go ahead and read some of the resources that helped me in the first place!

Resources

--

--

R. Parker
The KickStarter

MSc in Computer Science — Mainly focused on Productivity habits, technology and everything that attracts my attention