Of course! Let's break down super() in Python. It's a powerful and often misunderstood tool, but once you grasp the core concept, it becomes much easier to use.

The phrase "super pass" is a great way to think about it: super() is your tool to pass control up to a parent class.
The Core Idea: "Don't Repeat Yourself"
Imagine you have two classes, Child and Parent. The Child class inherits from Parent. Now, what if the Child class has a method that does something, but it also needs to do everything the Parent's version of that method does?
You could copy-paste the parent's code into the child's method. But this is a bad practice called code duplication. If you ever need to change the parent's logic, you have to remember to change it in the child too, which is error-prone.
super() solves this. It allows you to call a method from the parent class directly from within the child class.

The Simplest Case: Single Inheritance
This is the most common and straightforward use of super().
Let's create an Animal class and a Dog class that inherits from it.
class Animal:
def __init__(self, name):
print("Animal's __init__ is called.")
self.name = name
def speak(self):
print(f"{self.name} makes a sound.")
class Dog(Animal):
def __init__(self, name, breed):
# 1. Call the parent class's __init__ method
super().__init__(name)
# 2. Now, add Dog-specific attributes
print("Dog's __init__ is called.")
self.breed = breed
def speak(self):
# 1. Call the parent class's speak method
super().speak()
# 2. Now, add Dog-specific behavior
print(f"{self.name} barks!")
# --- Let's use it ---
my_dog = Dog("Rex", "Golden Retriever")
print("\n--- Calling the speak method ---")
my_dog.speak()
Output:
Animal's __init__ is called.
Dog's __init__ is called.
--- Calling the speak method ---
Rex makes a sound.
Rex barks!
What's happening here?

-
In
Dog.__init__:super().__init__(name)tells Python: "Hey, go up one level in the inheritance chain (toAnimal) and call its__init__method." This initializes thenameattribute.- Then, the
Dogclass continues and sets its ownself.breedattribute.
-
In
Dog.speak:super().speak()tells Python: "Go up one level and call thespeakmethod fromAnimal." This prints the generic sound.- Then, the
Dogclass continues and adds its own specific bark.
The "Pass" in Action: super() is passing the execution from the Dog class up to the Animal class to perform part of the job before returning to the Dog class to finish the job.
The Magic: super() with __init__ and the MRO
This is where super() gets really powerful, especially in more complex class hierarchies.
The Problem: The Diamond Inheritance
Consider this structure:
A
/ \
B C
\ /
D
Class D inherits from both B and C, which both inherit from A. If D calls super().__init__(), which class does it call? B? C? A?
Python uses the Method Resolution Order (MRO) to solve this. The MRO is a linear order that Python follows when looking for a method. It's based on the C3 linearization algorithm, which ensures a consistent order.
You can see the MRO of any class by calling ClassName.__mro__.
class A:
def __init__(self):
print("Initializing A")
class B(A):
def __init__(self):
print("Initializing B")
super().__init__()
class C(A):
def __init__(self):
print("Initializing C")
super().__init__()
class D(B, C):
def __init__(self):
print("Initializing D")
super().__init__()
# Let's see the MRO
print(D.__mro__)
# Output: (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <object>)
# Now let's create an instance of D
print("\nCreating an instance of D:")
d = D()
Output:
Creating an instance of D:
Initializing D
Initializing B
Initializing C
Initializing A
Why this order?
D.__init__()is called first. It prints "Initializing D".d = D()executessuper().__init__(). The MRO isD -> B -> C -> A. The next class afterDisB.B.__init__()is called. It prints "Initializing B" and then its ownsuper().__init__().- The next class in the MRO after
BisC. C.__init__()is called. It prints "Initializing C" and then its ownsuper().__init__().- The next class in the MRO after
CisA. A.__init__()is called. It prints "Initializing A".A's__init__has nosuper()call, so the chain stops.
The Key Takeaway: super() doesn't just mean "call the parent". It means "call the next method in the MRO". This ensures that in complex inheritance chains, every part of the initialization (or any method) is executed exactly once, in the correct order. This is the "pass" in action—it's passing the baton down the MRO line.
The Modern Way: super().__init__() vs. ParentClass.__init__()
You might see two ways to call a parent's method:
-
The
super()way (Modern & Recommended):super().__init__(name)
-
The "Direct Call" way (Older & Problematic):
ParentClass.__init__(self, name) # Or Animal.__init__(self, name)
Why is super() almost always better?
- Handles MRO Correctly: As we saw in the diamond example,
ParentClass.__init__(self, ...)would completely break. It would only callAnimal's__init__and skipC's entirely.super()automatically follows the correct MRO path. - More Flexible: If you change the parent class of
DogfromAnimaltoAwesomeAnimal, you don't have to remember to change everyAnimal.__init__call toAwesomeAnimal.__init__. Thesuper()call remains the same. - Less
selfTyping: You don't have to type out the parent class name andself.
Summary: The "Super Pass" Cheat Sheet
| Goal | The super() Way |
Why it's the "Pass" |
|---|---|---|
Call parent's __init__ |
super().__init__(args) |
Passes control to the next class in the MRO to initialize its part of the object. |
| Call parent's other method | super().some_method(args) |
Passes control to the next class in the MRO to execute its part of the method. |
| See the execution order | print(ClassName.__mro__) |
Shows you the line that super() will follow, helping you understand the "pass" sequence. |
| Avoid common pitfalls | Always use super() instead of ParentClass() |
super() is dynamic and respects the inheritance chain. Direct calls are brittle and break with multiple parents. |
Final Analogy: Think of super() as a relay race. Each class (Dog, Animal) is a runner. When a runner (Dog) finishes their leg of the race (their specific code), they hand the baton (super()) to the next runner in their lane (Animal). The MRO is the official map of the race route. super() ensures the baton is passed correctly and every runner gets to run.
