Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Super init vs. parent.__init__

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?

like image 650
Adam Hughes Avatar asked Mar 20 '15 18:03

Adam Hughes


People also ask

What does super () __ init __ do?

When you initialize a child class in Python, you can call the super(). __init__() method. This initializes the parent class object into the child class. In addition to this, you can add child-specific information to the child object as well.

Is super init necessary?

In general it is necessary. And it's often necessary for it to be the first call in your init. It first calls the init function of the parent class ( dict ).

Why does a class need to manually call a superclass's __ init __ method?

The main reason for always calling base class _init__ is that base class may typically create member variable and initialize them to defaults. So if you don't call base class init, none of that code would be executed and you would end up with base class that has no member variables.

What does super () do in Python?

The super() function is used to give access to methods and properties of a parent or sibling class. The super() function returns an object that represents the parent class.


2 Answers

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.

like image 195
unutbu Avatar answered Sep 21 '22 15:09

unutbu


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.

like image 26
Evan Avatar answered Sep 22 '22 15:09

Evan