Understanding __init__ and the Constructor
super() is a special syntax that calls a method from the parent class. In the context of __init__, super().__init__() ensures the parent class's initialization runs before the child class's initialization.
Try it: Classes, Instances and Attributes
How a class creates instances with __init__ and self, why an attribute read checks the instance's __dict__ before the class, why assigning through an instance never changes the class, how a class-level list is shared by every instance, and why obj.method(x) is Class.method(obj, x).
How it works
- Dog(...) makes a new, empty instance and calls Dog.__init__(new_object, ...); self.name = ... stores into that object's __dict__.
- Reading obj.attr looks in obj.__dict__ first, then in the class.
- Assigning obj.attr = value always writes obj.__dict__, so it shadows a class attribute for that one object only.
- Mutating a class-level list (self.tricks.append) changes the one list every instance shares.
- obj.method is found on the class and bound to obj, so obj.method(x) runs Class.method(obj, x).
Default run (30 steps): Ready: class Dog and the statements you picked. Watch where each attribute is found and where each assignment writes. … Finished. Printed: ['sit'] / Wolf / Canis familiaris / Fido is 5.
Simplified: The lab's own small Python interpreter runs a fixed, hand-written script (you choose the variant and the values, never the code); nothing is executed as real Python. Every script was run in CPython 3.12 with the same inputs and the lab reproduces its output and error messages. Object numbers are illustrative, not real id() values.
Loading the simulation…
The Initialization Handoff
When a child class provides its own __init__ method, it takes responsibility for the child-specific initialization process. The parent class may still have initialization work to perform. super().__init__() provides the handoff: it calls the parent class's initialization method so the parent attributes are initialized before the child-specific attributes are set.
What do you think happens?
A child class creates an instance and its __init__ method calls super().__init__(). Which initialization runs first?
Reveal answer
The parent initialization runs first, followed by the child-specific initialization.
In this context, super().__init__() calls the parent class's __init__ method. The child continues with its own attribute setup after that call returns.
What super() Calls
super() is special syntax that calls a method from the parent class. When it is followed by __init__(), super().__init__() calls the parent class's initialization method.
The name __init__ identifies the initialization method used by a class. A child class can define its own __init__ method to add child-specific setup, but that does not remove the parent class's initialization responsibility. Calling super().__init__() lets the child initialization method use the parent initialization method as part of the same setup process.
A Complete Initialization Trace
class Parent:
def __init__(self, name):
self.name = name
class Child(Parent):
def __init__(self, name, level):
super().__init__(name)
self.level = level
item = Child("Ari", 3)- 1The Child instance is created with the arguments "Ari" and 3.
- 2Child.
__init__begins and receives those arguments. - 3
super().__init__(name) callsParent.__init__(name), passing the name argument required by the parent initialization. - 4The parent initialization sets the parent-defined name attribute.
- 5Control returns to Child.
__init__, which sets the child-defined level attribute. - 6The resulting Child instance has both the parent attribute name and the child attribute level.
- Parent defines initialization for the name attribute.
- Child extends Parent and defines additional initialization.
super().__init__(name) calls the parent initialization with the required argument.- The child then sets its own level attribute.
- Creating item starts the child initialization sequence.
item.name
# "Ari"
item.level
# 3This example shows the execution order rather than two separate objects being assembled independently. The child instance contains the attribute initialized by the parent and the attribute initialized by the child. The parent and child initialization responsibilities therefore coexist in one child instance.
Skipping the Parent Setup
class Child(Parent):
def __init__(self, name, level):
self.level = levelThe child initialization sets only the child-specific attribute.
class Child(Parent):
def __init__(self, name, level):
super().__init__(name)
self.level = levelThe parent initialization runs before the child-specific attribute is set.
Common mistake Defining a child __init__ method but never calling super().__init__().
What it looks likeThe child sets level but does not call the parent initialization that sets name.
Why it failsThe parent initialization is skipped, so the parent-defined attribute is not initialized by that method.
Do this insteadCall super().__init__() in the child __init__ method before setting child-specific attributes.
Common mistake Calling super().__init__() with the wrong or missing arguments.
What it looks likeThe parent initialization requires name, but the child does not pass name.
Why it failsThe parent initialization must receive the correct arguments to initialize parent attributes.
Do this insteadPass the arguments required by the parent initialization method.
Common mistake Setting child-specific attributes before calling the parent initialization.
What it looks likeThe child assigns level and calls super().__init__() afterward.
Why it failsThe recommended initialization order is for the parent initialization to run before child-specific attributes are set.
Do this insteadPlace super().__init__() at the beginning of the child __init__ method.
Responsibilities Across the Class Relationship
| Part of the design | Initialization responsibility | Result in the child instance |
|---|---|---|
| Parent class | Initializes parent-defined attributes when its __init__ method runs | Parent attributes are available on the child instance |
| Child class | Adds child-specific initialization after calling super().__init__() | Child attributes are added to the same instance |
| super().__init__() | Connects the child initialization method to the parent initialization method | Parent setup occurs before child-specific setup |
The parent and child contribute different initialization responsibilities to one child instance.
A child class instance inherits the parent's attributes and methods and adds its own. The built-in dir() function can be used to inspect the names available on the instance, including inherited and child-provided members. The important point is that inheritance does not make the parent attributes disappear when child attributes are added; both sets can be part of the child instance.
Practice the Execution Order
Consider a Parent class whose __init__ method initializes a parent attribute, and a Child class whose __init__ method calls super().__init__() before initializing a child attribute. Write the execution order in four steps, beginning with creation of the Child instance and ending with the completed child-specific setup.
Hints
- Start with Child.
__init__. - Place the parent initialization immediately after the
super().__init__() call. - The child-specific attribute is set after the parent initialization returns.
Tracing the Handoff
A child instance is created using a child __init__ method that calls super().__init__() and then sets a child-specific attribute. What happens in order?
- 1Step 1
The child instance creation enters the child class's
__init__method. - 2Step 2
The child method executes
super().__init__(), which calls the parent class's initialization method. - 3Step 3
The parent initialization sets the parent-defined attributes using the arguments passed to it.
- 4Step 4
Control returns to the child method, which sets the child-specific attributes.
The completed child instance contains both the attributes initialized by the parent and the attributes initialized by the child.
Key Takeaways
- 1
super()calls a method from the parent class. - 2
super().__init__() calls the parent class's initialization method. - 3The parent initialization should run before child-specific attributes are set.
- 4The correct arguments must be passed to the parent initialization.
- 5A child instance can contain both parent-defined and child-defined attributes.
At a glance
super()connects a child class method to a parent class method.super().__init__() ensures that parent initialization runs before child-specific initialization.- The parent and child attributes can coexist in the same child instance.
- Always pass the correct arguments and call
super().__init__() at the beginning of the child__init__method.