Super Arguments in Python

Abid Ullah Oct 10, 2023
  1. Super Arguments in Python
  2. Super Uses Inheritance Concept
  3. Accurate Usage of Super Arguments in Python
  4. Use Super to Pass Arguments to Constructors in Python Multiple Inheritance
Super Arguments in Python

This article’s subject is using the Python super arguments correctly. We will also learn about the concept of super and inheritance, appropriate examples of code using super arguments, and the concept of base classes.

Super Arguments in Python

In Python, super invokes a method on another class. It is called a parent class, a base class, or a superclass when a class inherits from another class.

It is pretty straightforward to use super because it goes directly to the parent class and calls its methods.

Arguments can be passed to super. It takes two arguments, a class and a class instance.

Example Code:

class A:
    def roo(self):
        return "roo() from A"


class B(A):
    def roo(self):
        print("roo() from B")
        return super().roo()


class C(A):
    def roo(self):
        print("roo() from C")
        return super().roo()


class D(B, C):
    def roo(self):
        print("roo() from D")
        return super(C, self).roo()


a = A()
b = B()
c = C()
d = D()
print(a.roo())
print(b.roo())
print(c.roo())
print(d.roo())

Output:

roo() from A
roo() from B
roo() from A
roo() from C
roo() from A
roo() from D
roo() from A

Super Uses Inheritance Concept

Inheritance might seem unfamiliar if you are unfamiliar with object-oriented programming concepts. In object-oriented programming, inheritance refers to a class’s ability to derive (or inherit) attributes and behaviors from another class without implementing them again.

The convenient way to understand these concepts is to look at a code, so let’s create some classes to describe some shapes.

Example code:

class Rectangle_Shape:
    def __init__(self, len, wid):
        self.length = len
        self.width = wid

    def area(self):
        return self.length * self.width

    def perimeters(self):
        return 2 * self.length + 2 * self.width


class Square_Shape:
    def __init__(self, len):
        self.length = len

    def area(self):
        return self.length * self.length

    def perimeters(self):
        return 4 * self.length


s = Square_Shape(4)
print(s.area())
r = Rectangle_Shape(3, 5)
print(r.area())

This class has two corresponding classes: Rectangle_Shape and Square_Shape.

Output:

16
15

The example demonstrates two shapes that are related to one another: a square is a type of rectangle. The code does not reflect that relationship, resulting in essentially repeated code.

By using inheritance, you can reduce the amount of code you write while simultaneously reflecting the real-world relationship between rectangles and squares.

Example code:

class Rectangle_Shape:
    def __init__(self, length, width):
        self.length = length
        self.width = width

    def area(self):
        return self.length * self.width

    def perimeters(self):
        return 2 * self.length + 2 * self.width


# Making the Square_Shape class that initiates the Rectangle_Shape class
class Square_Shape(Rectangle_Shape):
    def __init__(self, len):
        super().__init__(len, len)


s = Square_Shape(4)
print(s.area())

In this case, super() calls init() of the Rectangle_Shape class, which is then used in the Square_Shape class without having to rewrite the code.

Output:

16

As shown in the example, Rectangle_Shape is the parent class, and Square_Shape is the child class.

Accurate Usage of Super Arguments in Python

The code for classes M, N, and O is below.

class M:
    def __init__(self):
        print("M initiated successfully")


class N(M):
    def __init__(self):
        super().__init__()
        print("N initiated successfully")


class O(N):
    def __init__(self):
        super(O, self).__init__()
        print("O initiated successfully")


o = O()

As the code above assumes, all classes overload their direct parents init() method. super() does not need any attributes, so using it without arguments suffices.

Output:

M initiated successfully
N initiated successfully
O initiated successfully

Suppose we want the class M2 to jump N’s init() method but run M’s init() method instead. The init() method should be inherited from M, not N, despite our class’ direct parent being N.

Here comes class M2. Let’s take a look at its execution.

class M:
    def __init__(self):
        print("M initiated successfully")


class N(M):
    def __init__(self):
        super().__init__()
        print("N initiated successfully")


class O(N):
    def __init__(self):
        super(O, self).__init__()
        print("O initiated successfully")


class M2(N):
    def __init__(self):
        super(N, self).__init__()
        print("other O initiated successfully")


m2 = M2()

It can be assumed from the code above that we pass attributes to the super() method to select the correct superclass this time. As a result of running m2 = M2(), we get the following output.

M initiated successfully
other O initiated successfully

Rather than calling the direct parent __init__() method, we invoked M’s init() Python method instead.

For implicit lookups using these statements or operators such as super()[name], super() is undefined.

Additionally, super() is not limited to using inside methods aside from the zero-argument form. Using the two-argument form identifies the arguments exactly and makes the appropriate references.

In a class definition, zero arguments only work because the compiler fills in the necessary details to retrieve the class and the instance.

Use Super to Pass Arguments to Constructors in Python Multiple Inheritance

A base class should be designed for multiple inheritances if you deal with various inheritances in general.

There are times when two classes have similar parameter names. When that happens, you cannot remove key-value pairs from **kwargs or remove them from *args.

It is possible to define a Base class, which, unlike an object, absorbs/ignores arguments.

Example code:

class Base(object):
    def __init__(self, *args, **kwargs):
        pass


class P(Base):
    def __init__(self, *args, **kwargs):
        print("P")
        super(P, self).__init__(*args, **kwargs)


class Q(Base):
    def __init__(self, *args, **kwargs):
        print("Q")
        super(Q, self).__init__(*args, **kwargs)


class R(P):
    def __init__(self, arg, *args, **kwargs):
        print("R", "arguments=", arg)
        super(R, self).__init__(arg, *args, **kwargs)


class S(Q):
    def __init__(self, arg, *args, **kwargs):
        print("S", "arguments=", arg)
        super(S, self).__init__(arg, *args, **kwargs)


class T(R, S):
    def __init__(self, arg, *args, **kwargs):
        print("T", "arguments=", arg)
        super(T, self).__init__(arg, *args, **kwargs)
        print("MRO---", [x.__name__ for x in T.__mro__])


t = T(10)

Output:

T arguments= 10
R arguments= 10
P
S arguments= 10
Q
MRO--- ['T', 'R', 'P', 'S', 'Q', 'Base', 'object']

It is important to note that Base must be the penultimate class in the MRO for this to work.

The Python programming language provides a wide range of features for Object-Oriented Programming. In that set, the super function arguments play an important role, especially when used correctly.

Hopefully, this article has helped you understand better how to use the super function arguments in Python.

Author: Abid Ullah
Abid Ullah avatar Abid Ullah avatar

My name is Abid Ullah, and I am a software engineer. I love writing articles on programming, and my favorite topics are Python, PHP, JavaScript, and Linux. I tend to provide solutions to people in programming problems through my articles. I believe that I can bring a lot to you with my skills, experience, and qualification in technical writing.

LinkedIn

Related Article - Python Argument