calling init for multiple parent classes with super? [duplicate]
Asked Answered
I

3

23

Possible Duplicate:
Can Super deal with multiple inheritance?

Python inheritance? I have a class structure (below), and want the child class to call the __init__ of both parents. Is this possible to do in a 'super' way or is it just a terrible idea?

class Parent1(object):
    def __init__(self):
        self.var1 = 1

class Parent2(object):
    def _init__(self):
        self.var2 = 2

class Child(Parent1, Parent2):
    def __init__(self):
        ## call __init__ of Parent1
        ## call __init__ of Parent2
        ## super(Child, self).__init__()
Inchoate answered 4/11, 2011 at 17:1 Comment(0)
C
27

Invocation via super doesn't call all the parents, it calls the next function in the MRO chain. For this to work properly, you need to use super in all of the __init__s:

class Parent1(object):
    def __init__(self):
        super(Parent1, self).__init__()
        self.var1 = 1

class Parent2(object):
    def __init__(self):
        super(Parent2, self).__init__()
        self.var2 = 2

class Child(Parent1, Parent2):
    def __init__(self):
        super(Child, self).__init__()

In Python 3, you can use super() instead of super(type, instance).

Chaplet answered 4/11, 2011 at 17:6 Comment(4)
I read many other questions and answers, yours is the only one that pointed out how super() calls the "next function in the MRO chain". A simple yet very important statement indeed.Imperium
For those that have no clue what MRO is: python.org/download/releases/2.3/mroConcatenate
What about if Parent1 and Parent2 are built in module classes?Luganda
I don't think this answer is correct and I agree with @Sven in his answer. I did a simple test on Python 3.7 and super() did call __init__() from all the parents. If you call a method that exists in both parent classes, only the method from the leftmost parent will be called. But super().__init__() will call __init__ of the parents from the rightmost to the leftmost.Conners
T
45

The idea of super() is that you don't have to bother calling both superclasses' __init__() methods separately -- super() will take care of it, provided you use it correctly -- see Raymond Hettinger's "Python’s super() considered super!" for an explanation.

That said, I often find the disadvantages of super() for constructor calls outweighing the advantages. For example, all your constructors need to provide an additional **kwargs argument, all classes must collaborate, non-collaborating external classes need a wrapper, you have to take care that each constructor parameter name is unique across all your classes, etc.

So more often than not, I think it is easier to explicitly name the base class methods you want to call for constructor calls:

class Child(Parent1, Parent2):
    def __init__(self):
        Parent1.__init__(self)
        Parent2.__init__(self)

I do use super() for functions that have a guaranteed prototype, like __getattr__(), though. There are not disadvantages in these cases.

Trippet answered 4/11, 2011 at 17:4 Comment(0)
C
27

Invocation via super doesn't call all the parents, it calls the next function in the MRO chain. For this to work properly, you need to use super in all of the __init__s:

class Parent1(object):
    def __init__(self):
        super(Parent1, self).__init__()
        self.var1 = 1

class Parent2(object):
    def __init__(self):
        super(Parent2, self).__init__()
        self.var2 = 2

class Child(Parent1, Parent2):
    def __init__(self):
        super(Child, self).__init__()

In Python 3, you can use super() instead of super(type, instance).

Chaplet answered 4/11, 2011 at 17:6 Comment(4)
I read many other questions and answers, yours is the only one that pointed out how super() calls the "next function in the MRO chain". A simple yet very important statement indeed.Imperium
For those that have no clue what MRO is: python.org/download/releases/2.3/mroConcatenate
What about if Parent1 and Parent2 are built in module classes?Luganda
I don't think this answer is correct and I agree with @Sven in his answer. I did a simple test on Python 3.7 and super() did call __init__() from all the parents. If you call a method that exists in both parent classes, only the method from the leftmost parent will be called. But super().__init__() will call __init__ of the parents from the rightmost to the leftmost.Conners
C
13

You could just call them directly with Parent.__init__(self):

class Parent1(object):
    def __init__(self):
        self.var1 = 1

class Parent2(object):
    def __init__(self):
        self.var2 = 2

class Child(Parent1, Parent2):
    def __init__(self):
        Parent1.__init__(self)
        Parent2.__init__(self)
        print(self.var1, self.var2)
Coleencolella answered 4/11, 2011 at 17:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.