super()
Cooperative multiple inheritance — call the parent's method without hard-coding the class name.
Common call
super().__init__(...)
Returns
a proxy — calls dispatch to the next class in the MRO
Replaces
`ParentClass.method(self, ...)` — but does not hard-code the parent name
Watch out
the zero-arg form only works INSIDE a method; outside you need the two-arg form
super() / super(type, obj_or_typeobj_or_type — The instance (or class) whose MRO to walk. The zero-arg form uses the first positional argument of the enclosing method.type: Any · default: self)
→ super
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| type | type | no (__class__) | The starting class for MRO lookup. In the zero-arg form (Python 3.0+), the compiler fills this in as the class the method is defined in. |
| obj_or_type | Any | no (self) | The instance (or class) whose MRO to walk. The zero-arg form uses the first positional argument of the enclosing method. |
Return value
super — A proxy object. Calling methods on it dispatches to the parent (next-in-MRO) class, bound to the current instance or class. `super()` inside a method (Python 3.0+) is equivalent to `super(__class__, self)` — the compiler fills in the arguments.
Common patterns
Extend __init__ in a subclass
The most common super() use — run the parent's initializer.
class Employee(Person): def __init__(self, name, salary): super().__init__(name) self.salary = salary
Extend a method
Call the parent method, then add subclass behavior.
class Loud(Talker): def speak(self): text = super().speak() return text.upper()
Cooperative multiple inheritance
Every class in the hierarchy calls super() — the MRO walks through each once.
class A: def do(self): print("A"); class B(A): def do(self): print("B"); super().do() class C(A): def do(self): print("C"); super().do() class D(B, C): def do(self): print("D"); super().do()
Two-arg form outside a method
When you need super() at module level or in a static context.
super(Employee, e).__init__(name)
Examples
1. Init
class Sub(Base):
def __init__(self, x):
super().__init__()
self.x = x
Returns
runs Base.__init__2. Method extension
class Loud(Talker):
def speak(self):
return super().speak().upper()
Returns
upcase result3. MRO walk
D.__mro__
Returns
(D, B, C, A, object)4. Zero-arg inside method
super().method()
Returns
next in MRO5. Two-arg outside method
super(D, d).method()
Returns
explicit start classPitfalls
1. Zero-arg super() only works INSIDE a method
The zero-arg form is compiler magic — it reads __class__ from the enclosing method definition. At module level or in a static function, it raises RuntimeError.
Outside method fails
# at module level super()
RuntimeError: super(): no arguments
Two-arg form
super(SomeClass, instance)
works anywhere
2. super() does NOT mean "parent class" — it means "next in MRO"
A single-inheritance mental model breaks with multiple inheritance. With diamond inheritance, super() may dispatch to a SIBLING class, not the "parent" you had in mind.
Assumed parent
# in D(B, C): # super() in B goes to A, right?
no — goes to C, then A
Read the MRO
D.__mro__
(D, B, C, A, object)
3. Must be a cooperative hierarchy — every class calls super()
If one class in the chain forgets to call super(), the MRO walk stops there. This is subtle in multi-inheritance code; the common convention is "every class calls super() for methods it might share".
One class breaks chain
class B(A): def do(self): print("B") # no super() — stops here
A.do never runs
Always call super()
class B(A): def do(self): print("B") super().do()
A.do runs after B
4. super() vs Parent.method(self) — subtly different
The hard-coded form works only for single inheritance. As soon as multiple inheritance appears, super() respects the MRO but the hard-coded form does not — leading to skipped classes or double-run methods.
Hard-coded skips MRO
class D(B, C): def do(self): B.do(self) # C.do never runs
diamond broken
super() follows MRO
class D(B, C): def do(self): super().do()
B and C both invoked
When to use
Use it
- Every __init__ in a subclass — the standard convention
- Extending any inherited method rather than replacing it
- Cooperative multiple inheritance and mixins
- When a subclass wants to add behavior around a parent method
Reach for something else
- Complete replacement of a parent method — do not call super()
- Naming ambiguity — if the parent method is unclear, refactor
- Deep hierarchies — often a sign that composition would be clearer
- When you truly want a specific class's method regardless of MRO — use ParentClass.method(self)
Notes
Complexity
O(1) proxy creation; O(mro depth) attribute lookup
Return
A super proxy — bound to the current instance
CPython impl
Objects/typeobject.c :: super_new
Memory
Small proxy object
Thread-safe
Yes for immutable class hierarchies
FAQ
If the parent has meaningful __init__ behavior, yes — otherwise inherited attributes will not initialize. The one exception: if you inherit directly from object and have no other cooperative parents, super().__init__() with no args is a no-op but still recommended for consistency.
History
2.2
super() introduced with new-style classes.
3.0
Zero-arg super() enabled by the compiler filling in __class__ and self.