Search code examples
pythonclasssuper

What's the point of super.init in a Python class definition referring back to the class that is being defined?


The example below was taken from a textbook on deep learning:

class BERTEncoder(nn.Module):
"""BERT encoder."""
def __init__(self, vocab_size, num_hiddens, ffn_num_hiddens, num_heads,
             num_blks, dropout, max_len=1000, **kwargs):
    super(BERTEncoder, self).__init__(**kwargs)
    

This is followed by regular init statements like self.something = something_else.

The super.init refers to the class that is being defined. What's the point in doing that and what does it do?


Solution

  • TL;DR super(BERTEncoder, self).__init__ looks for an __init__ method in self's MRO, skipping BERTEncoder itself and starting with the next class (in this case, nn.Module).


    Every class has a method-resolution order (MRO) which you can see using the mro method of the class.

    >>> class A: pass
    ...
    >>> class B(A): pass
    ...
    >>> class C(B): pass
    ...
    >>> class D(C): pass
    ...
    >>> D.mro()
    [<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
    

    The purpose of super is to start method lookup with a class other than the current class, and possibly using a different class's MRO altogether. super(x, y) is a proxy object; attribute lookup on the object uses the MRO of y, but starts with class x rather than whatever class is at the beginning of the MRO.

    Since any object's MRO starts with the type of the class itself, specifying the class's type effectively looks for an attribute in every ancestor class except for the class itself.

    Because this is far and away the most common way to use super, Python 3 (long ago) added machinery so that super() by itself implies the "current" class as the first argument and self as the second argument.