Understanding Python super with __init__ methods
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
super() is Python’s way to continue a method call along the method resolution order, or MRO. In __init__ methods that matters because object construction often needs cooperation from several classes, especially once inheritance becomes more than a simple single-parent case.
In Single Inheritance, super() Reuses Parent Initialization
The simplest case is a subclass that extends a base class:
Output:
Here, super().__init__(name) runs the next __init__ in the MRO, which in this simple example is the parent class Animal.
super() Means “Next in MRO,” Not “My Parent by Name”
That distinction becomes important with multiple inheritance. Consider this example:
Output:
super() in B does not jump straight to A. It goes to the next class in D’s MRO, which is C. That is why directly naming parent classes often breaks cooperative multiple inheritance.
Cooperative __init__ Methods Need Compatible Signatures
For cooperative inheritance to work well, each class should:
- accept the arguments it needs
- pass remaining arguments onward
- call
super().__init__
Example:
This pattern avoids duplicate initialization and lets each class consume only its own parameters.
Why Direct Base-Class Calls Can Be a Problem
You can write:
and in a simple inheritance tree that may appear to work. The problem is that direct base-class calls do not cooperate with the MRO. In a diamond-shaped hierarchy, that can lead to:
- duplicated initialization
- skipped classes
- tightly coupled code that breaks during refactors
super() exists to support cooperative dispatch across the full class hierarchy rather than hard-coding one parent call at a time.
Practical Rule of Thumb
If the class participates in inheritance and especially if multiple inheritance is possible, use super() consistently in every class in the chain.
If one class skips super() while the others use it, the chain stops there. That often creates confusing bugs because part of the object ends up initialized and part does not.
Common Pitfalls
The biggest mistake is assuming super() means “call my immediate parent class.” In Python it means “call the next implementation according to the MRO.”
Another common issue is mixing cooperative and non-cooperative classes. If some classes call super() and others directly name base classes, the initialization flow becomes fragile.
Developers also sometimes forget to design compatible __init__ signatures. Cooperative multiple inheritance works best when classes accept **kwargs and forward what they do not consume.
Finally, do not ignore __mro__. When behavior feels surprising, printing the MRO often explains exactly why super() is calling classes in a certain order.
Summary
- In
__init__,super()continues along the method resolution order. - In single inheritance, that usually looks like a parent-class call.
- In multiple inheritance, the MRO determines what runs next.
- Cooperative classes should call
super()and forward unused arguments cleanly. - Direct base-class calls can work in simple cases, but they are risky in reusable hierarchies.

