Concepts / Inheritance and Class Extension

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.

  • Programming
Interactive lab

Try it: Inheritance and Method Lookup

How a subclass inherits from its parent, how Python finds an attribute by walking the instance, then the class's method resolution order up to object, how overriding and super() work, why the same call does different things on different objects (polymorphism), and what isinstance / issubclass check.

How it works

  1. class Dog(Animal) gives Dog the MRO Dog → Animal → object; Puppy(Dog) gives Puppy → Dog → Animal → object.
  2. obj.name searches obj.__dict__, then each class of type(obj).__mro__ in order; the first class that defines the name wins, so a subclass method overrides the parent's.
  3. super().method() starts the search in the class after the one the current method was defined in, e.g. to run the parent's __init__.
  4. Calling the same method on a list of different objects runs each object's own version (polymorphism).
  5. isinstance(obj, C) is True when C is in type(obj).__mro__; if no class has the name, Python raises AttributeError.

Default run (63 steps): Ready: Animal, Dog, Cat and Puppy, then the statements you picked. Each attribute is searched along the class's MRO. … Finished. Printed: Rex the dog says Woof / Tom the cat says Meow / Bo the dog says Woof! / True / Puppy / Dog / Animal / object.

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. Single inheritance only (the lab's MRO code is Python's C3 algorithm, but no class here has two parents).

Educational simulation

Loading the simulation…

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.

Parent classattributes and methodsChild classinherited and added membersinherits and extends
What does the child class inherit from the parent, and what does it add?

The Delegation Path

Code walkthrough
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
  1. 1
    Creating a SavingsAccount begins the child class's __init__ method.
  2. 2
    super().__init__(owner) delegates to Account.__init__.
  3. 3
    The parent initializer sets owner.
  4. 4
    Control returns to SavingsAccount.__init__, which sets interest_rate.
  • Account defines the parent initialization.
  • SavingsAccount extends Account.
  • super().__init__(owner) calls the parent initializer with the required argument.
  • The child then initializes its own attribute.
SavingsAccount.__init__child setup beginsAccount.__init__owner is initializedSavingsAccount.__init__interest_rate isinitializedsuper().__init__(owner)returns control
How does control move from the child initializer to the parent initializer and then back to the child?

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.

Child instancecreation requestedChild __init__beginsParent __init__parent attributesChild __init__child attributesstartssuper().__init__()returns
What happens first, next, and last when both parent and child initializers run?
Worked example

Tracing a SavingsAccount

Determine which attributes are initialized when a SavingsAccount is created.

  1. 1
    Child initialization starts

    The SavingsAccount initializer receives owner and interest_rate.

  2. 2
    Parent initialization runs

    super().__init__(owner) calls Account.__init__, which sets the owner attribute.

  3. 3
    Child initialization resumes

    After the parent initializer returns, the child sets interest_rate.

Result

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.

SavingsAccountinstanceone instanceownerparent attributeinterest_ratechild attributecontainscontains
How can one child instance contain attributes initialized by both the parent and child classes?
Best practice

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

Before
class Account:
    def __init__(self, owner):
        self.owner = owner

class SavingsAccount(Account):
    def __init__(self, owner, interest_rate):
        self.interest_rate = interest_rate

The child initializer sets only the child-specific attribute.

After
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

The parent initializer runs first, then the child-specific attribute is set.

  • Common mistake

    Omitting super().__init__() from the child initializer.

    What it looks like

    The child sets interest_rate but never calls the parent initializer.

    Why it fails

    The parent attributes are not initialized by the parent initializer.

    Do this instead

    Call super().__init__() at the beginning of the child initializer.

  • Common mistake

    Calling super().__init__() without the required parent arguments.

    What it looks like

    The parent initializer requires owner, but the child call does not provide it.

    Why it fails

    The parent initializer needs the correct arguments to initialize its attributes.

    Do this instead

    Pass the arguments required by the parent initializer.

  • Common mistake

    Assuming that child-specific setup replaces parent setup.

    What it looks like

    The child initializer sets its own attributes and treats that as complete initialization.

    Why it fails

    A child instance inherits parent attributes and methods as well as adding its own.

    Do this instead

    Use super().__init__() so both parent and child initialization take place.

SavingsAccountchild attribute onlyinterest_rateinitializedSavingsAccountparent and child attributesownerinitialized by parentinterest_rateinitialized by childcontainscontainscontains
What changes in the resulting object when the child initializer calls super().__init__() versus when it omits that call?

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.

python

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

MEDIUM

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.
  1. 1
    Identify the parent class and the child class.
  2. 2
    Find the child initializer's super().__init__() call.
  3. 3
    Check that the arguments passed to super().__init__() match the parent initializer's needs.
  4. 4
    Trace the parent attribute initialization before the child attribute initialization.
  5. 5
    Confirm that both sets of attributes belong to the one child instance.

Key Takeaways

  1. 1
    super() calls a method from the parent class.
  2. 2
    super().__init__() runs the parent initialization method from the child initializer.
  3. 3
    The parent initializer should run before child-specific attributes are set.
  4. 4
    A child instance can contain both parent attributes and child attributes.
  5. 5
    dir() can be used to inspect attributes and methods available through the child instance.

At a glance

  • 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.

More concepts starting with I