Are You Really Using Python’s super() Correctly? Recommended to Bookmark

Are You Really Using Python's super() Correctly? Recommended to Bookmark

In your daily work, do you often see the line of code <span>super().__init__()</span> when reading Python source code?

What exactly does this line of code do?

Today, we will explain <span>super()</span> from 0 to 1, ensuring that you can use it flexibly after reading.

1- Introduction

<span>super()</span> is used to call methods from the parent class (or more accurately, the next class in the MRO mechanism).

For example, when we previously wrote inheritance, we might have written it like this:

class Animal:
    def __init__(self, name):
        self.name = name

class Dog(Animal):
    def __init__(self, name, breed):
        Animal.__init__(self, name)  # Directly call the parent class
        self.breed = breed

This approach is certainly fine, but if the inheritance chain is complex or involves multiple inheritance, writing out the parent class names one by one can be cumbersome and prone to bugs.

At this point, <span>super()</span> comes in handy.

2- Why Use super()

Using <span>super()</span> has the following 3 advantages:

  • • Conciseness: No need to repeatedly write the parent class name, reducing the chance of errors when changing the parent class name.
  • • Safety: In multiple inheritance, it automatically calls the next class’s method according to the MRO (Method Resolution Order).
  • • Maintainability: It is easier for others to understand the logic when they take over your code.

In simple terms, super() is the officially recommended “elegant inheritance approach”.

3- The Secret Behind MRO

How does super() know which class to call? The answer is MRO (Method Resolution Order).

Python has a set of sequential rules in the class inheritance chain, which can be viewed through <span>class_name.__mro__</span> in the source code.

For example:

class A:
    def show(self):
        print("A")

class B(A):
    def show(self):
        print("B")
        super().show()

class C(A):
    def show(self):
        print("C")
        super().show()

class D(B, C):
    def show(self):
        print("D")
        super().show()

print(D.__mro__)

The result is:

(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

When we call D().show(), the execution order is: D → B → C → A → object.

PS: super() does not simply look for the “parent class”; it searches downwards in this order.

4- Practical Example

First, let’s look at the case of single inheritance.

The code is as follows:

class Animal:
    def __init__(self, name):
        self.name = name

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)  # Call Animal's __init__
        self.breed = breed

dog = Dog("Wangcai", "Husky")
print(dog.name, dog.breed)

The output is: Wangcai Husky

Next, let’s look at the case of multiple inheritance.

The code is as follows:

class A:
    def say(self):
        print("A")

class B(A):
    def say(self):
        print("B")
        super().say()

class C(A):
    def say(self):
        print("C")
        super().say()

class D(B, C):
    def say(self):
        print("D")
        super().say()

d = D()
d.say()

The result is: D B C A

PS: It can be seen that super() runs step by step according to the MRO rules.

5- Conclusion

In fact, the core function of super() is to call the method of the next class in the MRO.

It should be noted that super() is not equal to the parent class; it is just the next stop in the MRO.

Therefore, it is recommended that you no longer write <span>parent_class.__init__()</span>; using super() is the more Pythonic way to go!

Leave a Comment