Python basics: super() usage

Overview

super() is a method in Python to call the parent class (super class). In the subclass, the super() method can be used to call the parent class's method. [Super class: refers to an inheritance relationship of more than 2 levels. If class C inherits class B, and class B inherits class A, then class A is the super class of class C]

effect:

  • Inheritance makes code maintenance easier
  • Solve the problems of repeated calls (diamond inheritance) and search order (MRO) caused by multiple inheritance

grammar:

super(type[, object-or-type])

Parameters:
type – class.
object-or-type – class, usually self

Another difference between Python 3 and Python 2 is: Python 3 can use super().xxx directly instead of super(Class, self).xxx:

Use of super

1. Call the __init__ constructor of the parent class through super():

class Person():
      def __init__(self):
        print('我是Peson的__init__构造方法')

class Student(Person):
        def __init__(self):
         super().__init__()
          print'我是Student的__init__构造方法')

stu = Student()
-----------------------------------------
我是Peson的__init__构造方法
我是Student的__init__构造方法

2 Use supper() to call the parent class method with the same name as the subclass
2.1 Single inheritance
In single inheritance, super is, as everyone thinks, mainly used to call the parent class method.

class A:
    def __init__(self):
        self.n = 2

    def add(self, m):
        print('self is {0} @A.add'.format(self))
        self.n += m

class B(A):
    def __init__(self):
        self.n = 3

    def add(self, m):
        print('self is {0} @B.add'.format(self))
        super().add(m)
        self.n += 3
b = B()
b.add(2)
print(b.n)

When we execute the above code, the output we get is as follows:

self is <__main__.B object at 0x106c49b38> @B.add
self is <__main__.B object at 0x106c49b38> @A.add
8

This result illustrates two issues:

1. super().add(m) indeed calls the add method of parent class A.
2. When super().add(m) calls the parent class method def add(self, m), self in the parent class is not an instance of the parent class but an instance of the subclass , so after b.add(2) The result is 5 instead of 4.

Additional notes:
MRO—method search order

  • MRO is method resolution order, which is mainly used to determine the calling path [sequence] of methods and attributes when inheriting. In fact, it is the sequence table when inheriting parent class methods.
  • Python provides a built-in attribute __mro__ for classes to view the search order of methods.
class C(A,B):
	pass
print(C.__mro__)
out:
(<class '__main__.C'>,<class'__main__.A'>,<class'__main__B'>,<class 'object'>)

When searching for methods, the output results of __mro__ are searched from left to right.

  • If a method is found in the current class, execute it directly without searching again.
  • If not found, check whether there is a corresponding method in the next class. If found, execute it directly without searching again.
  • If the last class is found but the method is still not found, the program will report an error.

2.2 Multiple inheritance
In multiple inheritance, there is an MRO (sequence table when inheriting parent class methods) call ordering issue. That is, the super method is executed strictly in accordance with the MRO order.

class A:
    def __init__(self):
        self.n = 2

    def add(self, m):
        print('self is {0} @A.add'.format(self))
        self.n += m

class B(A):
    def __init__(self):
        self.n = 3

    def add(self, m):
        print('self is {0} @B.add'.format(self))
        super().add(m)
        self.n += 3

class C(A):
    def __init__(self):
        self.n = 4

    def add(self, m):
        print('self is {0} @C.add'.format(self))
        super().add(m)
        self.n += 4

class D(B, C):
    def __init__(self):
        self.n = 5

    def add(self, m):
        print('self is {0} @D.add'.format(self))
        super().add(m)
        self.n += 5

d = D()
d.add(2)
print(d.n)
out:
self is <__main__.D object at 0x10ce10e48> @D.add
self is <__main__.D object at 0x10ce10e48> @B.add
self is <__main__.D object at 0x10ce10e48> @C.add
self is <__main__.D object at 0x10ce10e48> @A.add
19
  • Similarly, no matter how many times it is called, self in the parent class method is not an instance of the parent class but an instance of the subclass. In the above example, it is the instantiation object of D.
  • D.mro() == [D,B, C, A, object], the execution order of multiple inheritance will be strictly in accordance with the order of mro.
  • The overall call flow chart is as follows:
d = D()
d.n == 5
d.add(2)

class D(B, C):          class B(A):            class C(A):             class A:
    def add(self, m):       def add(self, m):      def add(self, m):       def add(self, m):
        super().add(m)  1.--->  super().add(m) 2.--->  super().add(m)  3.--->  self.n += m
        self.n += 5   <------6. self.n += 3    <----5. self.n += 4     <----4. <--|
        (14+5=19)               (11+3=14)              (7+4=11)                (5+2=7)

Insert image description here
Others:
1. Super().__init__ is basically the same as the class name. init in single inheritance.
2. But there is a difference in multiple inheritance. The super method can ensure that each parent class method will only be executed once. Methods using class names will cause the method to be executed multiple times.
3. When using multiple inheritance, use the super method. The reason for passing parameters to the parent class should be due to the super algorithm in python. All parameters must be passed, otherwise an error will be reported. 4. When using single inheritance, using the super method will not work
. Pass all, only the parameters required by the parent class method can be passed, otherwise an error will be reported

Guess you like

Origin blog.csdn.net/qq_44804542/article/details/116173195