Use super with __init__ in Python
Preserve initialization when overriding __init__, follow the method resolution order, and design cooperative multiple inheritance without passing stray arguments to object.
When a subclass defines its own __init__, Python does not automatically run the base implementation as well. Call super().__init__(...) if the subclass needs the initialization provided by the next class in its method resolution order, or MRO.
Extend initialization
class Person:
def __init__(self, name):
self.name = name
class Student(Person):
def __init__(self, name, student_id):
super().__init__(name)
self.student_id = student_id
student = Student("Alex", "S001")
print(student.name) # Alex
print(student.student_id) # S001
If Student.__init__ only assigns student_id, this example never assigns name; reading it raises AttributeError. The parent method still exists, but overriding it changes which method is called automatically. If the subclass defines no __init__, normal inheritance finds the inherited one.
Strictly, __new__ creates the instance and __init__ initializes it. Calling super().__init__ does not construct a second parent object.
Extend other methods too
class A:
def greet(self):
return "A"
class B(A):
def greet(self):
return super().greet() + " + B"
print(B().greet()) # A + B
super() is a proxy for continued attribute lookup; it is not limited to initialization.
Follow a cooperative MRO
class Root:
def __init__(self, **kwargs):
super().__init__(**kwargs)
class Named(Root):
def __init__(self, *, name, **kwargs):
self.name = name
super().__init__(**kwargs)
class Identified(Root):
def __init__(self, *, identifier, **kwargs):
self.identifier = identifier
super().__init__(**kwargs)
class Record(Named, Identified):
pass
record = Record(name="Alex", identifier="S001")
print([cls.__name__ for cls in Record.__mro__])
# ['Record', 'Named', 'Identified', 'Root', 'object']
Each participating method consumes its own arguments and forwards the rest once. Here, super() inside Named reaches Identified for a Record instance, even though Identified is not a direct base of Named. No unused keyword arguments should reach object.__init__, which does not accept them in this chain.
FAQ
Must super be the first line? No. The order depends on which state the cooperating methods expect. Establish a clear initialization contract rather than blindly putting the call first or last.
What if the base has no explicit initializer? The lookup continues through its MRO. Calling the next initializer keeps cooperative behavior possible, but pass only arguments the chain accepts.
Does the two-argument form still work? Yes. super(Student, self).__init__(name) remains valid in Python 3. The zero-argument form is the usual choice inside an ordinary instance method; it relies on compiler-provided class context and the method's first argument.
References
Contact us
Join the community
to join the community
Try Guance
Start online and pay only for what you use.
Get startedChoose a Guance plan