super() function in Python is a built-in function that allows you to access methods from a parent or sibling class. It is most commonly used within the context of inheritance, especially when you are overriding methods in a subclass and want to call the method from the parent class.
Understanding Inheritance and super( )
Inheritance is a fundamental concept in object-oriented programming that allows a class to inherit attributes and methods from another class. The class being inherited from is called the parent or superclass, and the class that inherits is called the child or subclass.
When overriding a method in a subclass, it is often necessary or beneficial to call the same method from the parent class. This is where
super() comes in handy.
Basic Syntax of super( )
The basic syntax of
super() is as follows:
method_name is the method from the parent class that you want to call, and
args are the arguments that this method requires.
How super( ) Works
When you use
super(), Python is actually looking for the next class in the method resolution order (MRO). The MRO is a list that defines the order in which base classes are searched when executing a method. First, it looks in the current class, and if it doesn’t find the method, it then looks in the classes that the current class inherits from, in the order they are listed in the class definition.
In a classic inheritance scenario where a subclass inherits from one superclass,
super() will simply refer to the superclass.
Advantages of Using super( )
- Maintainability: Using
super()makes your code more maintainable because you don’t have to hard-code the name of the superclass into every method call.
- Support for Multiple Inheritance:
super()is designed to handle complex multiple inheritance scenarios seamlessly. Without
super(), multiple inheritance can result in the same superclass being called more than once, leading to a variety of problems, one of which is the diamond problem.
- Dynamic Dispatch:
super()supports dynamic dispatch (which is the selection of a method at runtime) because it doesn’t hard-code the superclass. This is essential in cases where the class hierarchy is subject to change.
Using super( ) in Single Inheritance
To understand the use of
super() in single inheritance, it’s important to first grasp the basic concept of inheritance in object-oriented programming. Inheritance allows a class (known as a subclass) to inherit attributes and methods from another class (known as a superclass or parent class).
Single inheritance occurs when a subclass inherits from one superclass only. Here’s an example to illustrate single inheritance in Python:
class Parent: def __init__(self, value): self.value = value print("Parent class's __init__ method") def method_a(self): print("Parent class's method_a") class Child(Parent): def __init__(self, value, extra): super().__init__(value) self.extra = extra print("Child class's __init__ method") def method_b(self): print("Child class's method_b")
In this example,
Child is a subclass that inherits from
Parent class has an
__init__ method that initializes the object with a value, and a method named
Child class has its own
__init__ method and an additional method named
Using super( ) in __init__ Method
Child class uses
super() to call the
__init__ method of the
Parent class. This is crucial because it allows the
Child class to initialize part of its state in terms of the
Parent class’s initialization. Here is what happens when you create an instance of
child_instance = Child(10, 'extra data')
Childis called with
'extra data'as arguments.
super().__init__(value)is called. The
super()function returns a temporary object of the superclass (
Parent) which then allows you to call its methods.
__init__method is called with
10as the argument, setting
- Control returns to the
__init__method, and the
self.extraattribute is set to
- Finally, the message “Child class’s init method” is printed.
This sequence of operations ensures that the
Child object is properly initialized with the state defined in both the
Using super( ) with Other Methods
You can also use
super() to call other methods of the superclass, not just
__init__. This is often used when you want to extend or modify the behavior of a method from the superclass. Here’s how it’s done:
class Parent: def method_a(self): print("Parent class's method_a") class Child(Parent): def method_a(self): super().method_a() # Calls the same method from the Parent class print("Extension by Child class's method_a") child_instance = Child() child_instance.method_a()
When you call
method_a on an instance of
Child, here is what will happen:
- The overridden
Childclass is executed.
- Inside this method,
method_amethod from the
Parentclass, which will print “Parent class’s method_a”.
- After the
super()call, the next line
print("Extension by Child class's method_a")will execute, printing “Extension by Child class’s method_a”.
So, the output will be:
Parent class's method_a Extension by Child class's method_a
Using super( ) in Multiple Inheritance
Multiple inheritance is a feature in object-oriented programming where a class can inherit attributes and methods from more than one parent class. Python supports multiple inheritance and provides the
super() function to allow you to call methods in a parent class in the context of multiple inheritance.
How Multiple Inheritance Works in Python
In Python, when a class inherits from multiple parent classes, it creates a complex hierarchy where the interpreter needs a way to determine which parent class to refer to when a method is called. This is resolved using the Method Resolution Order (MRO).
The MRO is a rule-based system that Python uses to determine the order in which to look up a method. It’s a linearization of the hierarchy tree. Python uses the C3 linearization algorithm to determine the MRO in multiple inheritance scenarios.
Using super( ) in Multiple Inheritance
super() function is used to call the next method in the MRO. Here’s an example that illustrates the use of
super() in multiple inheritance:
class Base: def __init__(self): print("Base init") class A(Base): def __init__(self): super().__init__() print("A init") class B(Base): def __init__(self): super().__init__() print("B init") class C(A, B): def __init__(self): super().__init__() print("C init")
In the above classes:
Baseis the base class.
Bare subclasses that inherit from
Cinherits from both
When you create an instance of
__init__ method of
C is called, which in turn uses
super() to call the
__init__ method of the next class in the MRO, which is
__init__ method is then called, which also calls
super(), leading to
__init__ method, and so on until the base class’s
__init__ method is reached.
MRO and super( )
The MRO for class
C will look like this:
[C, A, B, Base, object]. Here’s how the MRO affects the calls:
Ais the first class after
Cin the MRO.
Base.__init__(), because of how the MRO is computed.
Base.__init__(), which is the next in line in the MRO.
Base.__init__()executes, and the initialization chain is complete.
Benefits of Using super( ) in Multiple Inheritance
- No Hardcoding Required:
super()eliminates the need to hardcode the superclass’s name, which can make changes to the inheritance hierarchy easier.
- Consistent Method Resolution:
super()follows the MRO, ensuring that the methods are called in the order Python intends based on the class hierarchy.
- Avoids Duplicating Calls: In complex inheritance hierarchies,
super()prevents the same superclass method from being called multiple times unintentionally.
Imagine you have a system where a
C class represents a widget that inherits from two classes:
A for touch functionality and
B for drawable functionality:
class Touch: def __init__(self): print("Touch capability added") class Drawable: def __init__(self): print("Drawable capability added") class Widget(Touch, Drawable): def __init__(self): super().__init__() print("Widget created with both capabilities")
When an instance of
Widget is created, it will print out the capabilities as they are initialized:
widget = Widget()
Touch capability added Widget created with both capabilities
The output will reflect the order defined by the MRO of
In multiple inheritance,
super() is an essential tool for calling superclass methods in a way that respects the MRO and avoids common pitfalls associated with multiple inheritance, such as duplicated method calls or the diamond problem. It ensures that each method in the inheritance hierarchy is called in a predictable and controlled manner, which is crucial for maintaining clean and functional object-oriented code in Python.
super() function is a powerful feature of Python that facilitates a cooperative method call dispatching mechanism. It is a critical part of the language’s support for inheritance, allowing for a clean and maintainable way to invoke superclass methods. The
super() function not only handles simple single inheritance but is also designed to operate correctly in complex scenarios with multiple inheritance, ensuring that each superclass’s methods are called in the order defined by the MRO. This makes
super() an essential tool for any Python programmer working with object-oriented code.