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! ๐Ÿš€

Top comments (0)