DEV Community

Nitinn S Kulkarni
Nitinn 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! πŸš€

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly β€” using the tools and languages you already love!

Learn More

Top comments (0)

πŸ‘‹ Kindness is contagious

Please leave a ❀️ or a friendly comment on this post if you found it helpful!

Okay