views:

8235

answers:

3

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 constructor in a constructor? If this still sounds too vague, here's some code.

class A(object):
    def __init__(self):
        print "Constructor A was called"

class B(A):
    def __init__(self):
        super(B,self).__init__()
        print "Constructor B was called"

class C(B):
    def __init__(self):
        super(C,self).__init__()
        print "Constructor 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 constructor for C - fair enough, B's constructor gets called. If you do the same in B, "self" still points to an instance of C so you end up calling B's constructor 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.

+14  A: 

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".

dF
I've had a really hard time deciding which answer to accept, but I will accept this one, simply because it is relevant to the version of python I am using.
shylent
In Python 2.6 I get `TypeError: super() argument 1 must be type, not classobj` using this method. Am I missing something?
Leopd
@Leopd: `super()` only works with new-style classes, i.e. you must inherit from `object`.
dF
+12  A: 

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

super().__init__(args)
ironfroggy
Nice! Clearly, this is something I've been looking for. Sadly, I am still stuck at python 2 (and for a long time, too, methinks).
shylent
A: 

This version for python 2.x does not hard-code the class name:

super(self.__class__,self).__init__(....
kpd
Nope, won't work. It will result in infinite recursion most of the time (as explained in the question), as .__class__ contains the type of the *instance*.
shylent