Chain-calling parent initialisers in python

PythonOopInheritanceConstructor

Python Problem Overview


Consider this - a base class A, class B inheriting from A, class C inheriting from B. What is a generic way to call a parent class initialiser in an initialiser? If this still sounds too vague, here's some code.

class A(object):
    def __init__(self):
	    print "Initialiser A was called"
    
class B(A):
    def __init__(self):
	    super(B,self).__init__()
        print "Initialiser B was called"
    
class C(B):
    def __init__(self):
	    super(C,self).__init__()
	    print "Initialiser C was called"
	
c = C()

This is how I do it now. But it still seems a bit too non-generic - you still must pass a correct type by hand.

Now, I've tried using self.__class__ as a first argument to super(), but, obviously it doesn't work - if you put it in the initialiser for C - fair enough, B's initialiser gets called. If you do the same in B, "self" still points to an instance of C so you end up calling B's initialiser again (this ends in an infinite recursion).

There is no need to think about diamond inheritance for now, I am just interested in solving this specific problem.

Python Solutions


Solution 1 - Python

Python 3 includes an improved super() which allows use like this:

super().__init__(args)

Solution 2 - Python

The way you are doing it is indeed the recommended one (for Python 2.x).

The issue of whether the class is passed explicitly to super is a matter of style rather than functionality. Passing the class to super fits in with Python's philosophy of "explicit is better than implicit".

Solution 3 - Python

You can simply write :

class A(object):

    def __init__(self):
        print "Initialiser A was called"

class B(A):
   
    def __init__(self):
        A.__init__(self)
        # A.__init__(self,<parameters>) if you want to call with parameters
        print "Initialiser B was called"

class C(B):

    def __init__(self):
        # A.__init__(self) # if you want to call most super class...
        B.__init__(self)
        print "Initialiser C was called"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionshylentView Question on Stackoverflow
Solution 1 - PythonironfroggyView Answer on Stackoverflow
Solution 2 - PythondF.View Answer on Stackoverflow
Solution 3 - PythonJay ParikhView Answer on Stackoverflow