Python Multiple inheritance not printing result as expected

Viewed 38

I have a code something like below. I was trying to test multiple-inheritance behaviour of python. I have a base class called Base and D1 and D2 is derived from base when D3 is derived from D1,D2. I Initialize D2 first and D1 from D3. I initialized D3 with val= 1 , D2 with D3.val+2 and D1 with D3.val+4 . But when I printed init values of all classes, I have noticed that D1 is being initialized with 3 temporarilly.

`

class Base:
    def __init__(self,val):
        print ("Base __init__",val)
        self.b_data = val
    def whoami(self):
        print ("I am Base")
    def val(self):
        print ("val of Base",self.b_data)

    def __del__(self):
        print ("Deleting Base")

  class D1(Base):

    def __init__(self,val):
        print ("D1 __init__",val)
        self.d1_data = val 
        super().__init__(self.d1_data)

    def whoami(self):
        print ("I am D1")
    def __del__(self):
        print ("Deleting D1")



class D2(Base):

    def __init__(self,val):
        print ("D2 __init__",val)
        self.d2_data = val +2
        super().__init__(self.d2_data)

    def whoami(self):
        print ("I am D2")
    def __del__(self):
        print ("Deleting D2")


class D3(D2,D1):

    def __init__(self,val):
        print ("D3 __init__",val)
        self.d3_data = val 

        super().__init__(self.d3_data) #callig D2 init
        super(D2,self).__init__(self.d3_data+4) #calling D1 init        
        #D2.__init__(self,100)

    def __del__(self):
        print ("Deleting D3")

if( __name__ == "__main__"):
    objD3 = D3(1)
    print ((objD3.__class__.__mro__))
    objD3.val()
    objD3.whoami()
`

But when I run it it shows me result as

D3 __init__ 1
D2 __init__ 1
D1 __init__ 3
Base __init__ 3
D1 __init__ 5
Base __init__ 5
(<class '__main__.D3'>, <class '__main__.D2'>, <class '__main__.D1'>, <class '__main__.Base'>, <class 'object'>)
val of Base 5
I am D2
Deleting D3

Can you please help me understand why at the 3rd line D1 __ init__ 3 is getting printed, When I am not initializing D1 with the value 3?

1 Answers

super may not be what you expect. Python has a concept of Method Resolution Order, and if you control what it is for D3 with print(D3.__mro__), you will find:

(<class '__main__.D3'>, <class '__main__.D2'>, <class '__main__.D1'>, <class '__main__.Base'>, <class 'object'>)

When super() is used in D2.__init__ for a D3 object, it will return a proxy to the next class in self.__class__.__mro__ which is D1 and not Base. And, because of that, it will call D1.__init__(3).

Related