Python super() vs Base.__init__ Method
Tags: django, flask, python
Published: 2024-01-08 08:58:15

---
title: Python super() vs Base.__init__ Method
published: true
date: 2024-01-08 08:58:00 UTC
tags: django,flask,python,pythonprogramming
canonical_url: https://bhavaniravi.medium.com/python-super-vs-base-init-method-d923ca595ad3
---

When defining a subclass, there are different ways to call the \_\_init\_\_ method of a parent class. Let’s start with a base class and go through each of these methods.

For this blog, it’s better that you open a sample.py python file and follow along.

```python
class Base(object):
    def __init__ (self):
        print "Base created"
```

### Method 1 :: Using Parent Reference Directly

```python
class ChildA(Base):
    def __init__ (self):
        Base. __init__ (self)
        print ("Child A initlaized")
```

### Method 2:: Using Super with child class

```python
class ChildB(Base):
    def __init__ (self):
        print ("Child B initlaized")
        super(ChildB, self). __init__ ()
```

### Method 3:: Using the super method

```python
class ChildC(Base):
    def __init__ (self):
        super(). __init__ ()
        print ("Child C initlaized")
```

### Questions

1. What are the pros and cons of each method?
2. Is there one single right way to do this?

When you run this code as a single Python script, initializing child classes A, B, and C., You will notice absolutely no difference.

```python
cA = ChildA()
cB = ChildB()
cC = ChildC()
```

How can we demystify this? Let’s start with the documentation.

1. As of [Python3](https://docs.python.org/3/library/functions.html#super) super() is same as super(ChildB, self).\_\_init\_\_(). That rules out one of the three methods.
2. To compare Base.\_\_init\_\_(self) and super().\_\_init\_\_() we need multiple Inheritance. Consider the following snippet

```python
class Base1:
    def __init__ (self):     
        print ("Base 1 created")     
        super(). __init__ ()

class Base2:
    def __init__ (self):     
        print ("Base 2created")     
        super(). __init__ ()
```

Let’s write the subclasses

```python
class A1(Base1, Base2):
    def __init__ (self):     
        print ("Child A1 Initialized")     
        super(). __init__ ()

class A2(Base2, Base1):
    def __init__ (self):     
        print ("Child A Initialized")     
        super(). __init__ ()
```

Let’s initialize the objects

```python
a1 = A1()
print ("\n\n")
a2 = A2()
```

On running the above snippet, we get the following Output.

```python
Base 1 created
Base 2 created
Child A1 initialized

Base 2 created
Base 1 created
Child A2 initialized
```

In the case of class A1(Base1, Base2) Base1 is initialized first, followed by Base2. It’s the inverse for class A2. We can conclude that the methods are called based on the order of specification.

1. When you use the Base1.\_\_init\_\_() method, you lose out on this feature of Python
2. When you introduce new hierarchies, renaming the classes will become a nightmare

So how does Python know which function to call first, introducing MRO(Method Resolution Order)

### Method Resolution Order

> Method Resolution Order(MRO) denotes the way a programming language resolves a method or attribute.

In the case of single inheritance, the attribute is searched only at a single level, with multiple inheritance Python interpreter looks for the attribute in itself then its parents in the order of inheritance. In case of A1 -> Base 1 -> Base 2

One can use the mro function to find the method resolution order of any particular class.

```python
print (A2.mro())
```

\*\* Output\*\*

```python
[<class ' __main__.A2'>, <class ' __main__.Base2'>, <class ' __main__.Base1'>, <class 'object'>]
```

### The Last Punch

Comment out the super calls in base class and check the ouput of your script.

```python
class Base1:
    def __init__ (self):
        print ("Base 1 created")
        # super(). __init__ () 

class Base2:
    def __init__ (self):
        print ("Base 2 created")
        # super(). __init__ ()
```

What do you see?

```python
Base 1 created
Child A1 initlaized
Base 2 created
Child A2 initlaized

[<class ' __main__.A2'>, <class ' __main__.Base2'>, <class ' __main__.Base1'>, <class 'object'>]
```

In spite of having Base1 and Base2 in the MRO list, mro won’t resolve the order unless the super() function is propagated all the way up to the base class, i.e., Python propagates the search for the attribute only until it finds one. Comment on the init method in Base1 and see for yourself.

```python
class Base1:
    pass

    # def __init__ (self):
    # self.prop1 = "Base 1"
    # self.prop11 = "Base 11"
    # print ("Base 1 created")
    # # super(). __init__ ()
```

**Output**

Since Python can’t find the \_\_init\_\_ method in Base1 it checks Base2 before sending it all the way to object class

```
Base 2 created
Child A1 initlaized

Base 2 created
Child A2 initlaized
[<class ' __main__.A2'>, <class ' __main__.Base2'>, <class ' __main__.Base1'>, <class 'object'>]
```

People ask me why I love Python so much. It’s not because Python is simple and easy. It is all these things Python does to make things easy for us, sometimes a little hard, too :)

[_Want to build a project with Python, Join the Python to Project Bootcamp](https://gumroad.com/l/LaFSj)