38

A Python subclass can be initialized with or without a call to super(), as shown below

class Parent(object):
    ...

class Child(Parent):

    def __init__(self):
        super(Child, self).__init__()


class Child(Parent):

    def __init__(self):
        Parent.__init__(self)

What is the difference between these cases, and is one generally preferable to the other?

Adam Hughes
  • 14,601
  • 12
  • 83
  • 122
  • Last one gives you `TypeError: unbound method __init__() must be called with Parent instance as first argument (got nothing instead)`, exactly because the argument is missing. – dhke Mar 20 '15 at 18:22
  • 1
    `Parent.__init__(self)` I believe you mean I like this method as it is more explicit to me... the MRO is scary black magic – Joran Beasley Mar 20 '15 at 18:27
  • Yes, sorry I guess I did mean that let me change it. – Adam Hughes Mar 20 '15 at 18:28
  • 1
    Make an [inheritance diamond](http://stackoverflow.com/q/5033903/190597). Then the super calls will invoke different `init` methods than the calls to `Parent.__init__`. – unutbu Mar 20 '15 at 18:29
  • So when inheriting from a single parent, is there no difference or preferred one to use? – Adam Hughes Mar 20 '15 at 18:32
  • If you only use single-inheritance, there is no difference. – unutbu Mar 20 '15 at 18:33
  • Is there a conventional preference? – Adam Hughes Mar 20 '15 at 18:35
  • They essentially do the same thing because a super call points to the parent class. – Malik Brahimi Mar 20 '15 at 18:55
  • Possible duplicate of [Difference between super() and calling superclass directly](https://stackoverflow.com/questions/21639788/difference-between-super-and-calling-superclass-directly) – Stevoisiak Feb 23 '18 at 16:52

2 Answers2

38

The purpose of super is to handle inheritance diamonds. If the class inheritance structure uses only single-inheritance, then using super() will result in the same calls as explicit calls to the "parent" class.

Consider this inheritance diamond:

class A(object):
    def __init__(self):
        print('Running A.__init__')
        super(A,self).__init__()

class B(A):
    def __init__(self):
        print('Running B.__init__')        
        super(B,self).__init__()

class C(A):
    def __init__(self):
        print('Running C.__init__')
        super(C,self).__init__()

class D(B,C):
    def __init__(self):
        print('Running D.__init__')
        super(D,self).__init__()

foo = D()

which prints

Running D.__init__
Running B.__init__
Running C.__init__
Running A.__init__

while if we change B to B2 and use explicit calls to the parent __init__:

class B2(A):
    def __init__(self):
        print('Running B.__init__')        
        A.__init__(self) 

class D2(B2,C):
    def __init__(self):
        print('Running D.__init__')
        super(D2,self).__init__()

bar = D2()

then the chain of init calls becomes

Running D.__init__
Running B.__init__
Running A.__init__

So the call to C.__init__ is skipped entirely.


There is no one preferred option.

If you can guarantee that you do not want to support multiple inheritance then explicit parent calls are simpler and clearer.

If you wish to support multiple inheritance now or in the future, then you need to use super(). But understand that there are some pitfalls involved with using super, but with proper use these pitfalls can be avoided.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • Maybe I'm missing something, but the second example doesn't actually seem to be calling the explicit class init. It just calls super, like the one above it. – Robert Rapplean Sep 30 '17 at 22:23
  • The 2nd example calls super in first place, but B2 is calling A.__init__ instead super(A,self).__init__(), and that what it means, A is not calling C becuase uses an explicit call. – Daniel Carrasco Marín Oct 18 '19 at 19:58
11

The primary purpose of super(Child, self).__init__() is allow initialization run properly in the case of multiple inheritance with diamond inheritance structures. If you explicitly call the base class constructors with multiple inheritance some initializers may be called twice. With single inheritance, there is no functional difference between using super and explicitly invoking the base class __init__() method. Note that because all python new-style classes subclass object, multiple inheritance always involves diamond inheritance.

super has a lesser benefit of reducing requires changes if you rename or change the base class.

In python 3, the arguments to super are optional, so you can just do super().__init__(). Python 2 still requires you to provide the arguments explicitly.

Mat Gessel
  • 562
  • 8
  • 17
Evan
  • 2,217
  • 15
  • 18