Python has the ability to make use of multiple inheritance, which allows a subclass to inherit functionality from multiple parent classes. Often times, multiple inheritances can be quite tricky, and some programming languages like Java strictly prohibit it. There are times when multiple inheritances can have its uses. It can be used to create objects that have two distinct sets of behaviors. Python makes use of something called the Method Resolution Order, or MRO, to determine how to inherit from more than one Superclass. Let’s take a look at how this works now.
Multiple Inheritance Example
In this code below, first we see there are two classes, Class One and Class Two, each of which defines an attribute. In Class One we have color
and in Class Two we have sound
. Then there is the third class named Class Three, which lists both Class One and Class Two as base classes, separated by a comma, and this is how you inherit from more than one class at the same time. In class Three there is a method to print out those attributes. The showprops()
method prints out self.color
and also prints out self.sound
, each of which is inherited from a different class (Multiple Inheritance).
class One():
def __init__(self):
super().__init__()
self.color = 'One color'
self.name = 'Set In Class One'
def karate_chop(self):
print('Whack!')
class Two():
def __init__(self):
super().__init__()
self.sound = 'Two sound'
self.name = 'Set In Class Two'
def karate_chop(self):
print('Super Whack!!')
class Three(Two, One):
def __init__(self):
super().__init__()
def showprops(self):
print(self.color)
print(self.sound)
print(self.name)
Instantiating An Object
obj_three = Three()
Here we instantiate the Three() class and assign it to the obj_three variable. Three() inherits from both classes One and Two. Notice however that since we pass in the inherited classes in reverse, Three(Two, One), it affects how the final object looks up attributes and methods. We can see how this works by looking at the method resolution order.
MRO
Python uses the C3 linearization algorithm to determine the order in which to resolve class attributes, including methods. This is known as the Method Resolution Order (MRO).
print(Three.__mro__)
(<class '__main__.Three'>, <class '__main__.Two'>, <class '__main__.One'>, <class 'object'>)
What this shows us is that class Three has the highest precedence, class Two the second, and class One the third. Keep this in mind when we run the code below.
obj_three.showprops()
One color Two sound Set In Class Two
obj_three.karate_chop()
Super Whack!!
Order Of Classes
What how the output of our code changes if we alter the definition of class Three.
class Three(One, Two):
def __init__(self):
super().__init__()
def showprops(self):
print(self.color)
print(self.sound)
print(self.name)
print(Three.__mro__)
(<class '__main__.Three'>, <class '__main__.One'>, <class '__main__.Two'>, <class 'object'>)
obj_three.showprops()
One color Two sound Set In Class One
obj_three.karate_chop()
Whack!
Both classes One and Two have a name attribute as well as a karate_chop() method. The value of that attribute and the output of that method are different based on the method resolution order resulting from how the Superclasses are passed into the Subclass. This is an important concept to be aware of when trying to implement multiple inheritances in Python.