Python super() Function
1. Introduction to super()
The super()
function in Python is used to call methods from a parent class in an inheritance hierarchy. It helps in maintaining code reusability, avoiding redundant code, and properly managing multiple inheritance scenarios.
Why do we need super()
?
- Method Overriding: When a child class overrides a method from its parent,
super()
allows calling the parent’s version of the method. - Extending Parent Methods: It allows calling the parent method without hardcoding the parent class name.
- Constructor Chaining: Helps in calling the constructor (
__init__
) of the parent class when initializing a subclass. - Multiple Inheritance Management: Ensures proper order of method execution when dealing with multiple base classes.
2. Basic Usage of super()
Example 1: Calling Parent Class Method
class Parent:
def greet(self):
print("Hello from Parent")
class Child(Parent):
def greet(self):
super().greet() # Calls the parent class method
print("Hello from Child")
# Create an instance of Child
c = Child()
c.greet()
Output:
Hello from Parent
Hello from Child
What happens here?
- The
Child
class overrides thegreet()
method of theParent
class. - Inside the
Child
class’sgreet()
,super().greet()
calls the parent’sgreet()
method before executing the child’s version. - This ensures both versions of
greet()
are executed.
Why use super()
instead of Parent.greet(self)
?
Using super()
dynamically resolves the method to call based on Method Resolution Order (MRO), which is crucial in multiple inheritance.
3. Calling Parent Constructor with super()
When a subclass defines its own constructor (__init__
), the parent class’s constructor is not automatically called. We must use super().__init__()
to ensure proper initialization.
Example 2: Using super()
to Call Parent Constructor
class Animal:
def __init__(self, species):
self.species = species
print(f"Animal created: {species}")
class Dog(Animal):
def __init__(self, name, breed):
super().__init__("Dog") # Calls the Parent class constructor
self.name = name
self.breed = breed
print(f"Dog created: {name}, Breed: {breed}")
# Creating a Dog instance
d = Dog("Buddy", "Golden Retriever")
Output:
Animal created: Dog
Dog created: Buddy, Breed: Golden Retriever
Explanation:
- The
Dog
class has its own constructor that takesname
andbreed
as arguments. - The
super().__init__("Dog")
call ensures that the Animal class constructor is executed first. - This allows the
species
attribute (fromAnimal
) to be initialized properly before setting upname
andbreed
inDog
.
4. Understanding Method Resolution Order (MRO)
Python follows a special order when resolving method calls in an inheritance hierarchy. This is known as the Method Resolution Order (MRO).
How to Check MRO?
You can check the MRO using:
print(ClassName.mro())
or
help(ClassName)
Example 3: Checking MRO
class A:
def show(self):
print("A's method")
class B(A):
def show(self):
print("B's method")
super().show()
class C(B):
def show(self):
print("C's method")
super().show()
c = C()
c.show()
print(C.mro()) # Prints Method Resolution Order
Output:
C's method
B's method
A's method
[<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>]
Key Points
super().show()
inC
callsshow()
fromB
, which then callsshow()
fromA
.- MRO follows the order
[C → B → A → object]
. object
is the ultimate parent of all classes in Python.
5. super()
in Multiple Inheritance
Example 4: Multiple Inheritance with super()
class A:
def show(self):
print("A's method")
class B(A):
def show(self):
print("B's method")
super().show()
class C(A):
def show(self):
print("C's method")
super().show()
class D(B, C): # Multiple inheritance
def show(self):
print("D's method")
super().show()
d = D()
d.show()
Output:
D's method
B's method
C's method
A's method
MRO for Class D
print(D.mro())
Output:
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
Key Observations
- Order is D → B → C → A because Python uses C3 Linearization to maintain consistency.
super()
ensures that each class is called only once, avoiding duplicate calls toA
.
6. Calling super()
with Arguments
Example 5: Passing Arguments
class Parent:
def __init__(self, name):
print(f"Parent constructor called for {name}")
class Child(Parent):
def __init__(self, name, age):
super().__init__(name) # Passing 'name' to the Parent constructor
print(f"Child constructor called for {name}, Age: {age}")
c = Child("Alice", 10)
Output:
Parent constructor called for Alice
Child constructor called for Alice, Age: 10
Key Points
- Arguments passed to
super()
are forwarded to the parent class constructor. - This ensures that all necessary attributes are initialized properly.
7. super()
in Static and Class Methods
Example 6: Using super()
in Class Methods
class Parent:
@classmethod
def greet(cls):
print(f"Hello from {cls.__name__}")
class Child(Parent):
@classmethod
def greet(cls):
super().greet()
print(f"Hello from {cls.__name__}")
Child.greet()
Output:
Hello from Parent
Hello from Child
Why does super()
work in class methods?
- Since class methods receive
cls
instead ofself
,super()
correctly resolves methods for the class.
8. Common Mistakes with super()
Calling super()
in a class without a parent
class A:
def method(self):
super().method() # ERROR: No parent class
Solution: Only use super()
in classes that inherit from another.
Forgetting super().__init__()
in inheritance
class A:
def __init__(self):
print("A initialized")
class B(A):
def __init__(self):
print("B initialized") # Forgot super().__init__()
b = B()
Fix: Use super().__init__()
inside B.__init__()
.
9. Summary
super()
calls parent class methods dynamically.- Works with single and multiple inheritance.
- Resolves methods using Method Resolution Order (MRO).
- Used in constructors, instance methods, class methods, and static methods.