How do I initialize the base (super) class?

Question:

In Python, consider I have the following code:

class SuperClass(object):
    def __init__(self, x):
        self.x = x
        
class SubClass(SuperClass):
    def __init__(self, y):
        self.y = y
        # how do I initialize the SuperClass __init__ here?

How do I initialize the SuperClass __init__ in the subclass? I am following the Python tutorial and it doesn’t cover that. When I searched on Google, I found more than one way of doing. What is the standard way of handling this?

Asked By: Jeremy

||

Answers:

Both

SuperClass.__init__(self, x)

or

super(SubClass,self).__init__( x )

will work (I prefer the 2nd one, as it adheres more to the DRY principle).

See here: http://docs.python.org/reference/datamodel.html#basic-customization

Answered By: adamk

Python (until version 3) supports "old-style" and new-style classes. New-style classes are derived from object and are what you are using, and invoke their base class through super(), e.g.

class X(object):
  def __init__(self, x):
    pass

  def doit(self, bar):
    pass

class Y(X):
  def __init__(self):
    super(Y, self).__init__(123)

  def doit(self, foo):
    return super(Y, self).doit(foo)

Because python knows about old- and new-style classes, there are different ways to invoke a base method, which is why you’ve found multiple ways of doing so.

For completeness sake, old-style classes call base methods explicitly using the base class, i.e.

def doit(self, foo):
  return X.doit(self, foo)

But since you shouldn’t be using old-style anymore, I wouldn’t care about this too much.

Python 3 only knows about new-style classes (no matter if you derive from object or not).

Answered By: Ivo van der Wijk

As of python 3.5.2, you can use:

class C(B):
def method(self, arg):
    super().method(arg)    # This does the same thing as:
                           # super(C, self).method(arg)

https://docs.python.org/3/library/functions.html#super

Answered By: Bob Jordan

How do I initialize the base (super) class?

class SuperClass(object):
    def __init__(self, x):
        self.x = x

class SubClass(SuperClass):
    def __init__(self, y):
        self.y = y

Use a super object to ensure you get the next method (as a bound method) in the method resolution order. In Python 2, you need to pass the class name and self to super to lookup the bound __init__ method:

 class SubClass(SuperClass):
      def __init__(self, y):
          super(SubClass, self).__init__('x')
          self.y = y

In Python 3, there’s a little magic that makes the arguments to super unnecessary – and as a side benefit it works a little faster:

 class SubClass(SuperClass):
      def __init__(self, y):
          super().__init__('x')
          self.y = y

Hardcoding the parent like this below prevents you from using cooperative multiple inheritance:

 class SubClass(SuperClass):
      def __init__(self, y):
          SuperClass.__init__(self, 'x') # don't do this
          self.y = y

Note that __init__ may only return None – it is intended to modify the object in-place.

Something __new__

There’s another way to initialize instances – and it’s the only way for subclasses of immutable types in Python. So it’s required if you want to subclass str or tuple or another immutable object.

You might think it’s a classmethod because it gets an implicit class argument. But it’s actually a staticmethod. So you need to call __new__ with cls explicitly.

We usually return the instance from __new__, so if you do, you also need to call your base’s __new__ via super as well in your base class. So if you use both methods:

class SuperClass(object):
    def __new__(cls, x):
        return super(SuperClass, cls).__new__(cls)
    def __init__(self, x):
        self.x = x

class SubClass(object):
    def __new__(cls, y):
        return super(SubClass, cls).__new__(cls)

    def __init__(self, y):
        self.y = y
        super(SubClass, self).__init__('x')

Python 3 sidesteps a little of the weirdness of the super calls caused by __new__ being a static method, but you still need to pass cls to the non-bound __new__ method:

class SuperClass(object):
    def __new__(cls, x):
        return super().__new__(cls)
    def __init__(self, x):
        self.x = x

class SubClass(object):
    def __new__(cls, y):
        return super().__new__(cls)
    def __init__(self, y):
        self.y = y
        super().__init__('x')
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.