Learnerslesson
   JAVA   
  SPRING  
  SPRINGBOOT  
 HIBERNATE 
  HADOOP  
   HIVE   
   ALGORITHMS   
   PYTHON   
   GO   
   KOTLIN   
   C#   
   RUBY   
   C++   




PYTHON - MULTIPLE INHERITANCE


We have seen that a Child class can have a Parent class. But as a matter of fact, a Child class can have Multiple Parent Classes.


Let us clarify with the below example.


Story :


As we have seen, the Supreme God had created the breathe( ) method in the 'LivingBeing' class.Also the Supreme God decided that in order to communicate, every living being should make some sound. i.e Humans will talk, dogs will bark, cats meao e.t.c.

Now, another master God came with another class named 'LivingOrganism' with two behaviours/methods,move (Like a fish swims, birds fly and humans walk) and breathe(As a Fish breathes oxygen from Water).

java_Collections

So, every other Gods who creates say, Fish, Bird, Human must inherit the 'LivingBeing' and 'LivingOrganism'.


Now, let us create the 'Human' class and inherit both the classes'LivingBeing' and 'LivingOrganism'.


Example :



class LivingBeing:

    def sound(self):
        print("Make a sound to communicate")
		
    def breathe(self):
        print("Breathes oxygen from Air")


class LivingOrganism:

    def move(self):
        print("Everyone should move")
		
    def breathe(self):
        print("Breathes oxygen from Air")


class Human(LivingBeing, LivingOrganism):

    def eat(self):
        print("Eats to survive")


human1 = Human()

human1.eat()

human1.move()

human1.breathe()


Output :



  Eats to survive
  Everyone should move
  Breathes oxygen from Air

So, we have defined the 'LivingBeing' class.


class LivingBeing:

    def sound(self):
        print("Make a sound to communicate")
		
    def breathe(self):
        print("Breathes oxygen from Air")

And defined the 'sound( )' and 'breathe( )' method in it.


Also, we have defined the 'LivingBeing' class.


class LivingOrganism:

    def move(self):
        print("Everyone should move")
		
    def breathe(self):
        print("Breathes oxygen from Air")

And defined the 'move( )' and 'breathe( )' method in it.


Now, if you see the 'breathe( )' method of 'LivingOrganism' class. It is specially designed for 'Fish' class. As the print statement says, 'Breathes oxygen from Air'.


def breathe(self):
    print("Breathes oxygen from Air")

Then we have defined the 'Human' class, inheriting the 'LivingBeing' and 'LivingOrganism'.


class Human(LivingBeing, LivingOrganism):

    def eat(self):
        print("Eats to survive")	

And the 'Human' class has just one method, i.e. 'eat( )'.


So, by inheritance. 'Human' class will have all the methods of 'LivingBeing' and 'LivingOrganism' class.


java_Collections

Then we have created the 'human1' object.


human1 = Human( )

And called the 'eat( )' and 'move( )' method.


human1.eat( )
human1.move( )

Then when we try calling the 'breathe( )' method, which 'breathe( )' method actually gets called?


human1.breathe( )

Since, both the classes 'LivingBeing' and 'LivingOrganism' has the 'breathe( )' method. It becomes a confusion that which 'breathe( )' method gets called?


Now, if we look at the output,


Breathes oxygen from Air

The 'breathe( )' method of 'LivingBeing' gets called. And to understand why ? Let us look at MRO or Method Resolution Order.


Method Resolution Order or MRO


So, in the above scenario the 'Human' class has two Parents. i.e. 'LivingBeing' and 'LivingOrganism'.And both 'LivingBeing' and 'LivingOrganism' has a method called 'breathe( )'.


Now to decide, which 'breathe( )' method would be called. Python follows a methodology called as Method Resolution Order or MRO.


Which says, if there are multiple parents, i.e. 'LivingBeing' and 'LivingOrganism'. Methods of 'LivingBeing' class would be called first as it is mentioned first in the 'Human' class.


java_Collections

And since, the 'LivingBeing' is the first one, so the 'breathe( )' method gets called first,ignoring the 'breathe( )' method of the 'LivingOrganism' class.


Use of super( ) Function


As we have seen in the previous tutorial that the 'super( )' Function is used in the child class to call a method of its Parent class.


Let us see, how it works with Multiple Inheritance.


Example :



class Supreme:

    def __init__(self):
        print("In the Supreme class")

class LivingBeing(Supreme):

    def __init__(self):
        print("In the LivingBeing class")
        super().__init__()

class LivingOrganism(Supreme):

    def __init__(self):
        print("In the LivingOrganism class")
        super().__init__()


class Human(LivingBeing, LivingOrganism):

    def __init__(self):
        print("In the Human class")
        super().__init__()
		
human1 = Human()


Output :



  In the Human class
  In the LivingBeing class
  In the LivingOrganism class
  In the Supreme class

So, in the above example, we have created called 'Supreme'.


class Supreme:

    def __init__(self):
        print("In the Supreme class")

Then we have created the 'LivingBeing' and 'LivingOrganism' class and inherited the 'Supreme' class in both 'LivingBeing' and 'LivingOrganism' class.


class LivingBeing(Supreme):

    def __init__(self):
        print("In the LivingBeing class")
        super().__init__()

class LivingOrganism(Supreme):

    def __init__(self):
        print("In the LivingOrganism class")
        super().__init__()

And we have the 'Human' class that inherits from 'LivingBeing' and 'LivingOrganism' class.


class Human(LivingBeing, LivingOrganism):

    def __init__(self):
        print("In the Human class")
        super().__init__()

java_Collections

Now, when we create the 'human1' Object.


human1 = Human( )

So, the '__init__( )' constructor of 'Human' class gets called first.


Now, in the '__init__( )' constructor of 'Human' class, a call to '__init__( )' is made using the 'super( )' Function.


def __init__(self):
    print("In the Human class")
    super().__init__()

And as per the, Method Resolution Order or MRO the '__init__( )' constructor of 'LivingBeing' gets called first.


def __init__(self):
    print("In the LivingBeing class")
    super().__init__()

Then once again, a call to '__init__( )' is made using the 'super( )' Function. And the '__init__( )' constructor of 'LivingOrganism' gets called second.


def __init__(self):
    print("In the LivingOrganism class")
    super().__init__()

And finally, 'super( ).__init__( )' calls the '__init__( )' constructor of 'Supreme' class.


And if you see the final output.


Output :



  In the Human class
  In the LivingBeing class
  In the LivingOrganism class
  In the Supreme class

You can see, 'Human' class gets called first, then 'LivingBeing' class, then 'LivingOrganism' class and finally, the Supreme class gets called.