29

Regarding multiple parent inheritance, when I call the super.__init__, why doesn't parent2's __init__ function get called? Thanks.

class parent(object):
    var1=1
    var2=2
    def __init__(self,x=1,y=2):
        self.var1=x
        self.var2=y

class parent2(object):
    var4=11
    var5=12
    def __init__(self,x=3,y=4):
        self.var4=x
        self.var5=y

    def parprint(self):
        print self.var4
        print self.var5

class child(parent, parent2):
    var3=5
    def __init__(self,x,y):
        super(child, self).__init__(x,y)

childobject = child(9,10)
print childobject.var1
print childobject.var2
print childobject.var3
childobject.parprint()

Output is

9
10
5
11
12
2
  • 2
    Side note: rhettinger.wordpress.com/2011/05/26/super-considered-super explains super quite well and shows how it can play nice with multiple inheritance. Commented Dec 31, 2011 at 13:04
  • 4
    PleaseCapitalizeClassNames Commented Jul 23, 2015 at 20:39

3 Answers 3

27

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):
        pass

class parent(Base):
    var1=1
    var2=2
    def __init__(self,x=1,y=2):
        super(parent,self).__init__(x,y)        
        self.var1=x
        self.var2=y

class 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.var5

class child(parent, parent2):
    var3=5
    def __init__(self,x,y):
        super(child, self).__init__(x,y)


childobject = child(9,10)
print childobject.var1
print childobject.var2
print childobject.var3
childobject.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.

Sign up to request clarification or add additional context in comments.

Comments

10

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

2 Comments

thanks, but for parent, it's superclass is object? how would it call into parent2?
MRO doesn't care what the current superclass is when MI is involved.
6

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 Construct
ParentA called by Child
ParentB called by ParentA
Base 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 Construct
ParentA called by Child
Base called by ParentA
[<class '__main__.Child'>, <class '__main__.ParentA'>, <class '__main__.ParentB'>, <class '__main__.Base'>, <class 'object'>]

More info about MRO

1 Comment

You should point out that your example is for Python 3. super() without arguments will fail in Python 2.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.