Inheritance and Class Extension
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.
One Instance, Two Initializers
When a child class extends a parent class, the child instance can contain attributes initialized by both classes. The child class adds its own setup, but the parent class's setup does not happen automatically inside the child's __init__ method. The child initializer must use super().__init__() to call the parent initializer.
The Delegation Path
class Account: def __init__(self, owner): self.owner = owner class SavingsAccount(Account): def __init__(self, owner, interest_rate): super().__init__(owner) self.interest_rate = interest_rate
Creation Order
The initialization order is deliberate. First, the child class's __init__ method begins. Next, super().__init__() calls the parent class's initialization method with the correct arguments. The parent initializer sets the parent attributes. Finally, execution returns to the child initializer, which sets the child-specific attributes. Calling super().__init__() at the beginning of the child initializer keeps this order explicit and ensures complete instance setup.
Tracing a SavingsAccount
Determine which attributes are initialized when a SavingsAccount is created.
Child initialization starts: The SavingsAccount initializer receives owner and interest_rate.
Parent initialization runs: super().__init__(owner) calls Account.__init__, which sets the owner attribute.
Child initialization resumes: After the parent initializer returns, the child sets interest_rate.
The resulting child instance contains the parent attribute owner and the child attribute interest_rate.
Combined Instance State
A child class instance inherits the parent class's attributes and methods and adds its own. In the generated example, owner comes from the parent initializer and interest_rate comes from the child initializer. These attributes coexist in the same child instance; they are not separate objects created by the two classes.
Place super().__init__() at the beginning of the child class's __init__ method. Pass the arguments required by the parent initializer. This allows the parent attributes to be initialized before the child-specific attributes are set.
When the Delegation Is Missing
Omitting super().__init__() from the child initializer.
The parent attributes are not initialized by the parent initializer.
Fix:
Call super().__init__() at the beginning of the child initializer.Calling super().__init__() without the required parent arguments.
The parent initializer needs the correct arguments to initialize its attributes.
Fix:
Pass the arguments required by the parent initializer.Assuming that child-specific setup replaces parent setup.
A child instance inherits parent attributes and methods as well as adding its own.
Fix:
Use super().__init__() so both parent and child initialization take place.
Checking Inherited Members
A child class inherits all attributes and methods from its parent class and adds its own. The source pack identifies dir() as one way to verify the members available through the child class. Use it as an inspection tool when you want to examine what the child class provides through inheritance and extension.
In this example, the parent initializer supplies owner, while the child initializer supplies interest_rate. The call to dir(account) can be used to inspect the attributes and methods available through the resulting child instance.
Practice the Trace
Create a parent class named Device with an __init__ method that initializes model. Then create a child class named Phone whose __init__ method accepts model and operating_system. Use super().__init__(model) before initializing operating_system. Finally, describe the order in which the two initializers run and list the attributes in one Phone instance.
Hints
- The parent initializer must receive the model argument.
- Place super().__init__(model) at the beginning of Phone.__init__.
- The completed instance should contain one parent attribute and one child attribute.
- Identify the parent class and the child class.
- Find the child initializer's super().__init__() call.
- Check that the arguments passed to super().__init__() match the parent initializer's needs.
- Trace the parent attribute initialization before the child attribute initialization.
- Confirm that both sets of attributes belong to the one child instance.
Key Takeaways
- super() calls a method from the parent class.
- super().__init__() runs the parent initialization method from the child initializer.
- The parent initializer should run before child-specific attributes are set.
- A child instance can contain both parent attributes and child attributes.
- dir() can be used to inspect attributes and methods available through the child instance.
Key Takeaways
- super() provides the delegation from a child class to its parent class.
- super().__init__() ensures that parent attributes are initialized before child-specific attributes.
- A child instance combines the attributes and methods inherited from the parent with the additions made by the child.
- The safest initialization pattern is to call super().__init__() at the beginning of the child initializer with the correct arguments.