7

anyone know what it means for following code on super(xxx, self).__init__()? what does it do? I though it should be class ABC inherits from other class but I do not see which class is inherited from.

class ABC:

    def __init__(self):
        super(ABC, self).__init__()
2
  • 7
    ABC implicitly inherits from object Commented Feb 24, 2020 at 14:48
  • Does this answer your question? What does 'super' do in Python? Commented Feb 24, 2020 at 14:58

3 Answers 3

8

super works with the method resolution order (MRO) of the class. The MRO always contains at least two classes: the class itself, and object (because all classes implicitly inherit from object)

>>> class ABC: pass
...
>>> ABC.__mro__
(<class '__main__.ABC'>, <class 'object'>)

If there are any explicitly named base classes in the class statement, those and their base classes will appear in the MRO somewhere between the new class and object.

>>> class ABC(str): pass
...
>>> ABC.__mro__
(<class '__main__.ABC'>, <class 'str'>, <class 'object'>)

Regarding your question "why super?", consider this standard example:

class A:
    def foo(self):
        print("A")


class B(A):
    def foo(self):
        super().foo()
        print("B")


class C(A):
    def foo(self):
        super().foo()
        print("C")


class D(B, C):
    def foo(self):
        super().foo()
        print("D")

The MRO for D is (D, B, C, A). Notice the call super().foo in B.foo. Looking only at the class B, you might assume that super().foo() is a call to A.foo. But when self is an instance of D (as is the case with D().foo(), for example), then super refers to C, not A, because C comes immediately after B in the MRO.

>>> D().foo()
A
C
B
D

foo outputs the classes in the MRO (sans object; A doesn't use super because A "introduced" foo into the hierarchy) in reverse order, from least to most specific.

Sign up to request clarification or add additional context in comments.

5 Comments

if so, why do i still need super here?
super is primarily used for multiple inheritance; it does not always refer to a class know to ABC at compile time.
super really should have been given a different name; in Dylan, the equivalent is called next-method.
but why super refer to C and not B?
@tamerlaha Not sure I follow. super() refers to different classes depending on where it is called. The value used as an implicit first argument is not statically determined, but determined by the runtime type of self. When self is an instance of D, super() in D.foo is a proxy for B. But then in B.foo, it is a proxy for C.
4

Classes without explicit bases automatically inherit from object. When called via ABC(), the super(ABC, self).__init__() inside ABC.__init__ executes object.__init__. This can be seen by checking the method resolution order.

>>> ABC.__mro__
(__main__.ABC, object)

Methods that do nothing but invoke the super method are generally not needed. However, when adding functionality it is common to invoke super even to refer to object.


Notably, super dispatch is not static, but can change via inheritance. Multiple inheritance can be used to inject another class between ABC and object in the method resolution order.

>>> class Intermediate:
...     def __init__(self):
...         print(f'Intermediate init of {self.__class__.__name__}')
...         super().__init__()
...
>>> class Alphabet(ABC, Intermediate):
...     """Compound of ABC and Intermediate"""
...
>>> Alphabet.__mro__                   # Intermediate is between ABC and object...
(__main__.Alphabet, __main__.ABC, __main__.Intermediate, object)
>>> Alphabet.__init__ is ABC.__init__  # ... but __init__ is still identical!
True
>>> Alphabet()  # Alphabet's ABC.__init__ delegates to Intermediate.__init__ ...
Intermediate init of Alphabet
>>> ABC()       # ... but ABC's ABC.__init__ still does not.

A class such as Intermediate is generally known as a mixin. In Python, classes intended to be used with mixins must use super instead of directly referring to superclass methods.

Comments

0

All classes implicitly inherit from object, just like in Java, unless they explicitly inherit from something else (which itself has to either implicitly inherit from object or from something else, and so on...).

A byproduct of this is that you can invoke any of object's methods on your object, ignoring your object's implementation of those methods, by doing what you've done:

>>> dir(object)
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
 '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__',
 '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
 '__sizeof__', '__str__', '__subclasshook__']

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.