We are going to learn about python multiple inheritance today. Before starting multiple inheritance, I suggest you to skim through Python Class and Python Inheritance if you are not familiar with them.
Table of Contents.
#definition of the class starts here class Person: #defining constructor def __init__(self, personName, personAge): self.name = personName self.age = personAge #defining class methods def showName(self): print(self.name) def showAge(self): print(self.age) #end of class definition # defining another class class Student: # Person is the def __init__(self, studentId): self.studentId = studentId def getId(self): return self.studentId class Resident(Person, Student): # extends both Person and Student class def __init__(self, name, age, id): Person.__init__(self, name, age) Student.__init__(self, id) # Create an object of the subclass resident1 = Resident('John', 30, '102') resident1.showName() print(resident1.getId()).
/usr/bin/python3.5 "/home/imtiaz/PycharmProjects/python tutorial - 1/multiple_inheritance.py" John 102 Process finished with exit code 0
Resolving the Conflicts with python multiple inheritance
Let’s have a look at another example.())
Class C inherits both A and B. And both of them has an attribute ‘name’. From which class the value of name will be inherited in C? Is it from A or B? What do you think? Well, the output is:
/usr/bin/python3.5 "/home/imtiaz/PycharmProjects/python tutorial - 1/multiple_inheritance.py" Richard Process finished with exit code 0
The name when printed is ‘Richard’ instead of ‘John’. Let’s try to understand what’s happening. The result would be same even if we declared class C as:
Class C(B, A):
The hierarchy becomes completely depended on the order of __init__() calls inside the subclass. To deal with it perfectly, there is a protocol named MRO (Method Resolution Order).
Method Resolution Order (MRO)
Let’s replace the previous code with a slightly modified version.
class A: def __init__(self): super().__init__() self.name = 'John' self.age = 23 def getName(self): return self.name class B: def __init__(self): super().__init__() self.name = 'Richard' self.id = '32' def getName(self): return self.name class C(A, B): def __init__(self): super().__init__() def getName(self): return self.name C1 = C() print(C1.getName())
Can you guess the output? Well, let’s find out.
/usr/bin/python3.5 "/home/imtiaz/PycharmProjects/python tutorial - 1/multiple_inheritance.py" John Process finished with exit code 0.
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
Pankaj!
Thank you very much!
Quite helpful in understanding Multiple Inheritance in Python
@srini
You can call super().__init__(name, age) but you would have to modify your __init in your A class to accept the age parameter only to be able to pass it to the second parent class __init__. Also add super.().__init__(age) to class A, this will pass age to class B.
Also you need to add super().__init__() in your parent classes, otherwise parent B __init__ never gets calles, check MRO rules online.
It is doable but will make your code ugly, stick to separate calles as sugested by the author
Hi Pankaj,
In the above example, the initializer is not taking input from the C’s instance.
Incase if i wish to initialize the parent constructors from child class instance, how should i use the super() to initialize.
example.
class A:
def __init__(self, name):
self.name = name
def getName(self):
return self,name
class B:
def __init__(self, age):
self.age = age
def getAge(self):
return self.age
class C(A, B):
def __init__(self, name, age, mobile):
# how to use super() to initialize both of my parent classes?
# super().__init__(name), followed by another super().__init__(age) initializing only name variable not age variable
Any idea?
Use
A.__init__()and
B.__init__(), I don’t think we can use super() in this case.
@Pankaj, you can if u add *args, and **kw to all __init__ and super().__init__(), so that it won’t care about the number of args
Hi All,
I have a question related to multiple inheritance, kindly help
Here is my sample code
class Animal():
”’ This is the base class”’
def __init__(self):
print(“I am animal”)
def who_am_i(self):
print(“Animal class”)
class Dog(Animal):
”’ This is subclass inheriting parent class ”’
def __init__(self):
print(“This is init of Dog class”)
def who_am_i(self):
print(“This is from Dog class and not from Animal class”)
class Cat(Dog):
”’This is the class inheriting subclass ”’
pass
myanimal = Animal()
mydog = Dog()
mycat = Cat()
When I call the method
mycat.who_am_i()
I will get the output “This is from Dog class and not from Animal class”
Is there a way to print “Animal Class” by calling mycat object.
Please help me, thanks in advance
Hi ,
I agree of the mro prints (, , , ).
when i added a print statement to all __init__ method of classes i am seeing a different output which i am not able to understand. please find the below code with output.
class A:
def __init__(self):
super().__init__()
print(“class A”)
self.name = ‘John’
self.age = 23
class B:
def __init__(self):
super().__init__()
print(“class B”)
self.name = ‘Richard’
self.id = ’32’
class C(A, B):
def __init__(self):
super().__init__()
print(“class C”)
def getName(self):
return self.name
C1 = C()
print(C1.getName())
print(C.__mro__)
output is as below :
class B
class A
class C
John
(, , , )
when the class order is C > A > B why the init method of B is getting invoked. please let me know if i misunderstood something.
Thanks
Your example and comments are very helpful indeed. The only point that needs to be cleared I think is that the order of execution of __init__ calls and the order of resolution of MRO for the getName() call is the same. Is that correct ? For that purpose I have added print statements at the BEGINNING of each __init__ to reveal the order in which constructors are called when you create an instance of C class.
That was really helpful. Can you please provide a tutorial on multi level inheritance?