DEV Community

Nitin S Kulkarni
Nitin S Kulkarni

Posted on

Mastering super() in Python – How It Works and Best Practices

🚀 Introduction

In Python, super() is essential for calling methods from parent classes, especially in multiple inheritance. It ensures that:

✅ Parent class methods are called properly

✅ All necessary initializations happen in the correct order

✅ We avoid redundant calls to parent classes

In this post, we’ll cover:

✔️ How super() works internally

✔️ Using super() in single and multiple inheritance

✔️ Understanding MRO (Method Resolution Order) in super()

✔️ Common pitfalls and best practices

1️⃣ Understanding super() – What Does It Do?

🔹 super() returns a proxy object that delegates method calls to a parent or sibling class.

🔹 Basic Example – Calling Parent Class Method


class Parent:
    def greet(self):
        print("Hello from Parent!")

class Child(Parent):
    def greet(self):
        super().greet()  # Calls Parent's method
        print("Hello from Child!")

c = Child()
c.greet()

Enter fullscreen mode Exit fullscreen mode

🔹 Output:


Hello from Parent!
Hello from Child!

Enter fullscreen mode Exit fullscreen mode

✅ super().greet() calls Parent.greet(), ensuring both methods execute correctly.

2️⃣ Using super() in init() Methods

🔹 Without super() – Manual Calling of Parent init()


class A:
    def __init__(self):
        print("Initializing A")

class B(A):
    def __init__(self):
        print("Initializing B")
        A.__init__(self)  # Manually calling A’s __init__

b = B()

Enter fullscreen mode Exit fullscreen mode

🔹 Output:


Initializing B
Initializing A

Enter fullscreen mode Exit fullscreen mode

❌ Problem:

Manually calling A.__init__(self) is not scalable for multiple inheritance.
Enter fullscreen mode Exit fullscreen mode

🔹 Using super() – The Right Way


class A:
    def __init__(self):
        print("Initializing A")

class B(A):
    def __init__(self):
        print("Initializing B")
        super().__init__()  # Calls A’s __init__

b = B()

Enter fullscreen mode Exit fullscreen mode

✅ Why Use super()?

Handles multiple inheritance correctly.
Automatically follows MRO to prevent redundant calls.
Enter fullscreen mode Exit fullscreen mode

3️⃣ super() in Multiple Inheritance (MRO in Action)

🔹 The Diamond Problem in Multiple Inheritance


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):  # Multiple inheritance
    def __init__(self):
        print("Initializing D")
        super().__init__()

d = D()

Enter fullscreen mode Exit fullscreen mode

🔹 Output (following MRO):


Initializing D
Initializing B
Initializing C
Initializing A

Enter fullscreen mode Exit fullscreen mode

✅ Why does this order occur?


print(D.mro())
# [D, B, C, A, object]

Enter fullscreen mode Exit fullscreen mode
super() ensures all parent classes are initialized exactly once.
MRO determines the order: D → B → C → A → object.
Enter fullscreen mode Exit fullscreen mode

4️⃣ When Not to Use super()

🔹 Using super() When Parent Class Does Not Have the Method


class A:
    pass

class B(A):
    def greet(self):
        super().greet()  # ❌ ERROR: A does not have greet()

b = B()
b.greet()  # AttributeError: 'super' object has no attribute 'greet'

Enter fullscreen mode Exit fullscreen mode

✅ Fix: Always check if the parent defines the method before calling super().

5️⃣ Common Pitfalls and Best Practices

✅ Always Use super() Instead of Explicit Parent Calls


class Parent:
    def greet(self):
        print("Hello from Parent!")

class Child(Parent):
    def greet(self):
        Parent.greet(self)  # ❌ Avoid this!
Enter fullscreen mode Exit fullscreen mode

✔️ Correct Way:


class Child(Parent):
    def greet(self):
        super().greet()  # ✅ This follows MRO

Enter fullscreen mode Exit fullscreen mode

✅ Always Call super().init() in init()


class Parent:
    def __init__(self):
        print("Parent initialized")

class Child(Parent):
    def __init__(self):
        print("Child initialized")
        super().__init__()

c = Child()

Enter fullscreen mode Exit fullscreen mode

✔️ Ensures parent class is properly initialized.

✅ Check MRO Before Using super() in Multiple Inheritance


print(ClassName.mro())  # Helps debug method resolution issues

Enter fullscreen mode Exit fullscreen mode

✅ Use super() Consistently Across a Class Hierarchy

If some classes use super() but others don’t, unexpected behavior may occur.

6️⃣ Summary

✔️ super() calls methods from parent classes following MRO.

✔️ In multiple inheritance, super() ensures each class is called only once.

✔️ Use super() in init() to ensure proper initialization.

✔️ Avoid manually calling parent methods—use super() instead!

🚀 What’s Next?

Next, we'll explore Python’s Abstract Base Classes (ABC) and enforcing class structures! Stay tuned.

💬 Got questions? Drop them in the comments! 🚀

Top comments (1)

Collapse
 
mohammed_anas_a754ccc1c28 profile image
Mohammed anas

Thank you, this is beneficial.