Python multi-inheritance, __init__ Python multi-inheritance, __init__ python python

Python multi-inheritance, __init__


If you want to use super in child to call parent.__init__ and parent2._init__, then both parent __init__s must also call super:

class parent(Base):    def __init__(self,x=1,y=2):        super(parent,self).__init__(x,y)   class parent2(Base):    def __init__(self,x=3,y=4):        super(parent2,self).__init__(x,y)

See "Python super method and calling alternatives" for more details on the sequence of calls to __init__ caused by using super.


class Base(object):     def __init__(self,*args):        passclass parent(Base):    var1=1    var2=2    def __init__(self,x=1,y=2):        super(parent,self).__init__(x,y)                self.var1=x        self.var2=yclass parent2(Base):    var4=11    var5=12    def __init__(self,x=3,y=4):        super(parent2,self).__init__(x,y)        self.var4=x        self.var5=y    def parprint(self):        print self.var4        print self.var5class child(parent, parent2):    var3=5    def __init__(self,x,y):        super(child, self).__init__(x,y)childobject = child(9,10)print childobject.var1print childobject.var2print childobject.var3childobject.parprint()

You might be wondering, "Why use Base?". If parent and parent2 had inherited directly from object, then super(parent2,self).__init__(x,y) would call object.__init__(x,y). That raises a TypeError since object.__init__() takes no parameters.

To workaround this issue, you can make a class Base which accepts arguments to __init__ but does not pass them on to object.__init__. With parent and parent2 inheriting from Base, you avoid the TypeError.


Because parent is next in method resolution order (MRO), and it never uses super() to call into parent2.


See this example:

class Base(object):     def __init__(self, c):        print('Base called by {0}'.format(c))        super().__init__()class ParentA(Base):    def __init__(self, c):        print('ParentA called by {0}'.format(c))        super().__init__('ParentA')class ParentB(Base):    def __init__(self, c):        print('ParentB called by {0}'.format(c))        super().__init__('ParentB')class Child(ParentA, ParentB):    def __init__(self, c):        print('Child called by {0}'.format(c))        super().__init__('Child')Child('Construct')print(Child.mro())

This will output:

Child called by ConstructParentA called by ChildParentB called by ParentABase called by ParentB[<class '__main__.Child'>, <class '__main__.ParentA'>, <class '__main__.ParentB'>, <class '__main__.Base'>, <class 'object'>]

Python multiple inheritance is like a chain, in Child class mro, the super class of ParentA is ParentB, so you need call super().__init__() in ParentA to init ParentB.

If you change super().__init__('ParentA') to Base.__init__(self, 'ParentA'), this will break the inheritance chain, output:

Child called by ConstructParentA called by ChildBase called by ParentA[<class '__main__.Child'>, <class '__main__.ParentA'>, <class '__main__.ParentB'>, <class '__main__.Base'>, <class 'object'>]

More info about MRO