Explain Codes LogoExplain Codes Logo

How to invoke the super constructor in Python?

python
functions
inheritance
constructor
Anton ShumikhinbyAnton Shumikhin·Dec 27, 2024
TLDR

When extending a class in Python, trigger the parent class' constructor using super().__init__(args). This is integral to preserving the parent’s initialization process:

class Parent: def __init__(self, value): self.value = value class Child(Parent): def __init__(self, value, added_value): super().__init__(value) # Let there be Parent! self.added_value = added_value # And Child said "Let there be more!"

In this code snippet, the Child class invokes Parent's __init__ method via super() – setting the foundation for proper inheritance.

Core understanding of the super() function

Molding Python 3 vs. Python 2

In Python 3, super() has been streamlined, calling the parent class without needing additional parameters:

super().__init__(args)

In Python 2, however, you'll require the current class and instance as arguments to super():

super(CurrentClassName, self).__init__(args)

Remember, Python 2 demands new-style classes (inheriting from object).

Superhero of multiple inheritance

The strength of super() lies in its capability to handle the MRO (Method Resolution Order). It safeguards correct method calls, especially in multiple inheritance terrains, avoiding the infamous diamond problem.

The direct call alternative

Sometimes, you might encounter a direct call to the parent constructor:

BaseClassName.__init__(self, args)

This seems explicit, but may turn into a spider-web when faced with multiple inheritance.

Words of caution

  • For Python 2.x, every class in the inheritance chain must descend from object.
  • Using super(self) could lead you down a rabbit hole—it's incorrect. Instead, use super(CurrentClassName, self).
  • Always hit the super constructor inside child class's __init__ to ensure it's up and running optimally.

Visualising super():

Think of initiating super constructor as building a subclass (your house 🏠) on an existing superclass (the foundation 🏗):

class SubclassHouse(SuperclassFoundation): def __init__(self): super().__init__() # We're laying the foundation...🏗🧱

When the foundation is set, your house inherits everything from the parent's 'genes' i.e., superclass's properties:

🏠 is up and sturdy, inheriting all 🏗's properties!

Construction extended: Overriding and augmenting constructors

At times, overwriting the entire constructor feels overkill, and extending it sounds apt. Super() got your back:

class ExtraRoomHouse(SuperclassFoundation): def __init__(self, unique_room): super().__init__() # Inherits existing features self.unique_room = unique_room # Added a unique touch 🎯

Skyscrapers: Multi-level inheritance

For multi-level inheritance, super() cascades the constructor calls from top to bottom—just like a waterfall:

class Grandparent: def __init__(self): self.grandpa_wisdom = True class Parent(Grandparent): def __init__(self): super().__init__() # Unleashes the wisdom of the ancients self.parent_coolness = True class Child(Parent): def __init__(self): super().__init__() # And wisdom rained down, with a touch of coolness self.child_creativity = True

Child.__init__() calls Parent.__init__(), further calling Grandparent.__init__(). Just like a wildlife food chain!

The intricate web of multiple inheritance

Multiple inheritance can be perplexing, primarily due to the diamond problem. Luckily, super() sprints to rescue with its MRO prowess, ensuring each class constructor is summoned once.