EXPLAINING SUPER () IN PYTHON
Tags: python, programming
Published: 2023-08-18 09:06:55

super() in Python is a built-in function that provides a way to call methods and access attributes from a parent class in an object-oriented programming context, particularly in situations involving inheritance. It allows you to achieve method overriding and multiple inheritance while maintaining control over the method resolution order (MRO).

In essence, super() returns a temporary object that represents the parent class in the current class’s context. This allows you to call methods and access attributes of the parent class without explicitly naming the parent class, which is especially useful when dealing with complex class hierarchies and multiple inheritance.

The general syntax for using super() is:

`class ChildClass(ParentClass):
    def some_method(self):
        super().method_name()
`

Here are some key points about super():

- Method Resolution Order (MRO): Python follows the C3 linearization algorithm to determine the order in which classes are searched for a method or attribute. super() respects this order and ensures that methods are called in the correct sequence.
- Passing Arguments: When using super() to call a method from a parent class, you don’t need to pass self as an argument explicitly. The super() call automatically includes the current instance as the first argument.
- Multiple Inheritance: super() is particularly useful in multiple inheritance scenarios, where a class inherits from multiple parent classes. It helps in avoiding ambiguity when accessing methods from parent classes with the same name.
- Mixin Classes: super() can be useful in situations where you have “mixin” classes that provide specific behavior, and you want to compose these mixins together while retaining the ability to call methods from the individual mixins.
- Flexibility: super() provides flexibility by allowing you to control which parent class’s method you want to call. You can specify a particular parent class when calling super(), which enables you to navigate the class hierarchy and choose the desired method.
- Cooperative Hierarchies: super() encourages cooperative method overriding and helps avoid code duplication by promoting a clear and systematic way of accessing and extending parent class methods.

Let us take an example code

```
class Bird:
    def __init__(self, name):
        self.name = name
 
    def speak(self):
        return f"{self.name} speaks"
 
 
class Sparrow(Bird):
    def speak(self):
        return super().speak() + " as chirp chirp"
 
 
robin = Sparrow('robin')
print(robin.speak())
```


In the above code, how the code works:

- Defining the Bird Class: The Bird class is defined with an __init__ method that takes a name parameter and initializes the instance variable name with the provided name. Additionally, it has a speak method that returns a string indicating that the bird is speaking.
- Defining the Sparrow Class: The Sparrow class is derived from the Bird class using inheritance. It overrides the speak method to provide its own implementation of bird speech. In this case, it calls super().speak() to invoke the speak method of the parent class (Bird) and then appends ” as chirp chirp” to indicate the specific sound of a sparrow.
- Creating an Instance of Sparrow: An instance of the Sparrow class is created and assigned to the variable robin. The constructor of the Sparrow class (__init__ method) is called with the argument 'robin' to set the name attribute of the robin instance.
- Calling the speak Method: The speak method of the robin instance is called using robin.speak(). Here’s what happens:
- The overridden speak method of the Sparrow class is executed.
- Inside the Sparrow class’s speak method, super().speak() is called. This invokes the speak method of the parent class (Bird).
- The Bird class’s speak method returns the string "robin speaks".
- The Sparrow class’s speak method appends ” as chirp chirp” to the returned string, resulting in "robin speaks as chirp chirp".
- Printing the Result: robin speaks as chirp chirp

Let us try a multiple inheritance

```
class Bird
    def __init__(self, name):
        self.name = name
  
    def speak(self):
        return f"{self.name} speaks"
 
class FlyingBird(Bird):
    def fly(self):
        return f" and {self.name} can fly"
 
 
class SwimmingBird(Bird):
    def ability(self):
        return   f"  {self.name} can swim"
 
 
class Swan(SwimmingBird, FlyingBird):
    def feature(self):
        return super().speak() + " woo woo " + super().ability() + super().fly()
          
 
lenny = Swan('lenny')
print(lenny.feature())
```


Let’s break down the code step by step:

- Defining Classes:
- FlyingBird: This class defines a method called fly, which returns a string indicating that the bird can fly. It inherits from the Bird class, although the Bird class definition isn’t provided in the code snippet.
- SwimmingBird: This class defines a method called ability, which returns a string indicating that the bird can swim. Similar to FlyingBird, it’s expected that this class inherits from the Bird class.
- Swan: The Swan class inherits from both SwimmingBird and FlyingBird using multiple inheritance. It defines a method called feature, where you intend to use super() to call methods from the parent classes.
- Creating an Instance:An instance of the Swan class is created and assigned to the variable lenny. The constructor of the Swan class isn’t provided in the code snippet, but we’ll assume that the __init__ method of the Bird class is used to initialize the name attribute.
- Calling the feature Method:The feature method of the lenny instance is called using lenny.feature(). Here’s what happens:
- Inside the feature method of the Swan class:
- super().speak(): This calls the speak method of the parent class in the method resolution order (MRO). Since Bird is the parent class that defines the speak method, it returns a string indicating that lenny speaks.
- super().ability(): This calls the ability method of the parent class in the MRO, which is SwimmingBird in this case. It returns a string indicating that lenny can swim.
- super().fly(): This calls the fly method of the parent class in the MRO, which is FlyingBird. It returns a string indicating that lenny can fly.
- Concatenating Results:The results of the three super() calls are concatenated together with spaces between them using the + operator.
- Printing the Result:The concatenated result of the super() calls is printed using the print() function.

Hence the output will be :

**lenny speaks woo woo lenny can swim and lenny can fly**


It is important note that the line :

```
return super().speak() + " woo woo " + super().ability() + super().fly()
```

first time super().speak()  reference the parent class Bird() and then invoke the speak method, then second and third time, it reference to the parent classes FlyingBird() and SwimmingBird() then invokes methods ability() and fly()

So we can understand how super() can be used to access the methods from different and multiple parent classes

This demonstrates how the super() function allows you to access methods from parent classes in a multiple inheritance scenario, preserving the method resolution order and allowing for customization of behavior.

It’s important to understand that while super() is a powerful tool, it should be used with care to prevent unexpected behavior, especially in complex class hierarchies.

more Python code samples : [https://github.com/jeevanism/python-learn/](https://github.com/jeevanism/python-learn/)