SoFunction
Updated on 2024-12-13

Examples of Super Usage in Python Explained

Python Super Usage

In this article, we're going to introduce super, which I'm sure is the way most people use super;

# That is, I have a class, say Male, and I inherit from another class, say Person, and I call its parent's initialization function in the init function of Male, which is its subclass, with super(). __init__() in the init function of Male, its subclass.
from objprint import op
class Person:
    def __init__(self, name):
         = name
class Male(Person):
    def __init__(self, name):
        super().__init__(name)
         = "male"
m = Male('xiaoyang')
op(m)

# Output:
<Male 0x23669a19fa0
  .gender = 'male',
  .name = 'xiaoyang'
>

When we use super, we usually think of it as a method or a function, but it's actually a proper class, it's a built-in name, and super() doesn't call a function, super() creates a super object.

>>> type(super)
<class 'type'>

Although we more commonly use super() with nothing inside the parentheses, the full version of super has two arguments, the first of which is a type, which is a class, and the second of which is a type or an object, where the second argument determines which object or class the function is bound to, and the second argument determines which object or class is used. The second argument determines which object or class the function is bound to, and the second argument determines whichmroand the first parameter determines which class to start looking for backward in the mro chain, for example;

from objprint import op
class Person:
    def __init__(self, name):
         = name

class Male(Person):
    def __init__(self, name):
        # super().__init__(name)
        super(Male, self).__init__(name)
         = "male"

m = Male('xiaoyang')
op(m)

# Output:
<Male 0x171f680afa0
  .gender = 'male',
  .name = 'xiaoyang'
>

# Actually, if we look at what we just did with super(). __init__(name) which is equivalent to super(Male, self). __init__(name).

So this.super(Male, self)It does this, first it gets the mro from the self object, then it finds the first argument, that is, the position of Male in the mro, and in the current case Male is the first one (Male Person object), then it looks for the class after Male, then it finds the first one, which is Person. Next, he will start to look for the class after Male, then the first thing he finds is Person, then he will see if there is a__init__This function is then found to be there, and then it's putting the__init__binds to self, which in this case can be interpreted as the Person's__init__The self passed in by the function is the self inside the super, which means that thePerson.__init__(self,name)This line of code is equivalent tosuper(Male, self).__init__(name)This line of code.

As for why you don't just usePerson.__init__(self,name)is for several reasons:

  • In the future, the name of the base class may be changed, or even the inheritance method may be changed, in which case you don't need to worry about anything if you use super, because he will automatically follow the mro to find the correct class, but if you use this kind of class, you have to change everything, which is more likely to cause errors.
  • In fact, super is dynamic, it looks for self's mro, and self, which is the argument that's passed in, is dynamic itself, which means that within the same function, I can use super to get a different class without changing the function.

In looking at this example:

from objprint import op

class Animal:
    def __init__(self, age):
         = age

class Person(Animal):
    def __init__(self, age, name):
        super().__init__(age)
         = name

class Male(Person):
    def __init__(self,age, name):
        # super(Male, self).__init__(age, name) 
        super(Person, self).__init__(age, name) 
         = "male"

m = Male(18, 'xiaoyang')
op(m)

If you use it properly in Malesuper(Male, self).__init__(age, name) then it will initialize everything normally, and it will access the Person's__init__ and then Person's__init__will access Animal's__init__The last thing you need to do is to finish this Male.

So what if we change it tosuper(Person, self).__init__(age, name) then an error will be reported because when we use thesuper(Person, self)The first parameter of self is Male Person Animal and then object. Since the first parameter is Person, he will start from the class after Person, that is, Animal.__init__function, but Animal's__init__ There is only one parameter age, so when we pass in age name that's wrong, then we just need to change it to only pass in an age such as:super(Person, self).__init__(age) That's all it takes, and it also skips Person.

To summarize what the two arguments to super, the first type and the second type or object, determine:

The first one only determines where to start looking in the mro chain.

The second is the object that determines the use of this function and the mro

super isn't just for use inside a class, it can be used anywhere, I just have to give the second argument object or class, and given where to start looking for the first argument, I can use its function, for example:

# Then here we're looking for the __init__ function that starts after Male on the mro of the object m, which actually finds the __init__ function of Person, and then we use Person's __init__ function to initialize m, the object.
from objprint import op

class Animal:
    def __init__(self, age):
         = age

class Person(Animal):
    def __init__(self, age, name):
        super().__init__(age)
         = name

class Male(Person):
    def __init__(self,age, name):
        super(Person, self).__init__(age)
         = "male"

m = Male(18, 'xiaoyang')
op(m)

print("----------------------")

super(Male, m).__init__(20, "xiaoyang")
op(m)

# Output:
<Male 0x18412d13f70
  .age = 18,
  .gender = 'male'
>
----------------------
<Male 0x18412d13f70
  .age = 20,
  .gender = 'male',
  .name = 'xiaoyang'
>

P.S. Typical usage of super

Many people intuitively understand super as calling a method in the parent class:

class A:
    def test(self):
        print('')

class B(A):
    def test(self):
        super().test()
        print('')

b = B()
()


The implementation results are:


From the above example, it seems that super can indeed call methods in the parent class. But look at the code below:

class A:
    def test(self):
        print('')

class TestMixin:
    def test(self):
        print('')
        super().test()

class B(TestMixin, A):
    def test(self):
        print('')
        super().test()


b = B()
()

Print results:



The above code first creates B's object b and then calls (), but B's test function, via super(), calls the test function of its first parent, TestMixin, because TestMixin is B's first parent.

The test function in TestMixin calls the test function in A via super, but A is not the parent class of TestMixin. In this inheritance system, both A and TestMixin are parents of B, but A has no inheritance relationship with TestMixin. Why does super in TestMixin call the test function in A?

summarize

This article on the use of Python Super is introduced to this article, more related Python Super detailed content please search for my previous articles or continue to browse the following related articles I hope you will support me in the future!