Home  >  Article  >  Backend Development  >  Detailed explanation of super() method in Python

Detailed explanation of super() method in Python

爱喝马黛茶的安东尼
爱喝马黛茶的安东尼forward
2019-08-22 17:27:132377browse

Detailed explanation of super() method in Python

1. Call the parent class method separately

Requirements: Write a class, and then write a subclass Inherit and use the subclass to call method 1 of the parent class.

Use method 1 to print: Fat boss, come and pack betel nuts.

Then first write a parent class of the fat boss and execute it:

class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('FatFather的name是%s' % self.name)
        print('FatFather的init调用结束')
def main():
    ff = FatFather("胖子老板的父亲")

Run the constructor init of the fat boss parent class as follows:

if __name__ == "__main__":
    main()
FatFather的init开始被调用
FatFather的name是胖子老板的父亲
FatFather的init调用结束

Okay, then Let's write a subclass, that is, the Fat Boss class, which inherits the above class.

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('调用FatFather类的name是%s' % self.name)
        print('FatFather的init调用结束')
# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby):
        print('胖子老板的类被调用啦!')
        self.hobby = hobby
        FatFather.__init__(self, name)  # 直接调用父类的构造方法
        print("%s 的爱好是 %s" % (name, self.hobby))
def main():
    #ff = FatFather("胖子老板的父亲")
    fatboss = FatBoss("胖子老板", "打斗地主")

In the above code, I use FatFather.init(self,name) to directly call the method of the parent class.

The running results are as follows:

if __name__ == "__main__":
    main()
胖子老板的类被调用啦!
FatFather的init开始被调用
调用FatFather类的name是胖子老板
FatFather的init调用结束
胖子老板 的爱好是 打斗地主

2. Basic concepts of super() method

In addition to the method of directly using FatFather.init(self,name) , and can also be called using the super() method.

Then first you need to read the description and syntax of the super() method to understand the use of the super() method.

2.1 Description

The super() function is a method used to call the parent class (super class).

super is used to solve the problem of multiple inheritance. Calling the parent class method directly with the class name is no problem when using single inheritance. However, if you use multiple inheritance, it will involve search order (MRO) and repeated calls. (Diamond inheritance) and other issues.

MRO is the method parsing sequence table of the class. In fact, it is the sequence table when inheriting the parent class method.

Related recommendations: "Python Video Tutorial"

2.2 Syntax

The following is the syntax of the super() method:

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

Parameters

type -- class

object-or-type -- class, usually one of self

Python3.x and Python2.x The difference is: Python 3 can use super().xxx directly instead of super(Class, self).xxx:

Python3.x Example:

class A:
    pass
class B(A):
    def add(self, x):
        super().add(x)

Python2.x Example:

class A(object):   # Python2.x 记得继承 object
    pass
class B(A):
    def add(self, x):
        super(B, self).add(x)

2.3 Single inheritance uses super()

Use the super() method to rewrite the init construction method of the fat boss inheriting the parent class just now

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('调用FatFather类的name是%s' % self.name)
        print('FatFather的init调用结束')
# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby):
        print('胖子老板的类被调用啦!')
        self.hobby = hobby
        #FatFather.__init__(self,name)   # 直接调用父类的构造方法
        super().__init__(name)
        print("%s 的爱好是 %s" % (name, self.hobby))
def main():
    #ff = FatFather("胖子老板的父亲")
    fatboss = FatBoss("胖子老板", "打斗地主")

Use from above When using the super method, it can be used directly because it is single inheritance.

Run as follows:

if __name__ == "__main__":
    main()
胖子老板的类被调用啦!
FatFather的init开始被调用
调用FatFather类的name是胖子老板
FatFather的init调用结束
胖子老板 的爱好是 打斗地主

So why is it said that single inheritance can be used directly? Because if the super() method has multiple inheritance, it will involve an MRO (sequence table when inheriting the parent class method) call ordering problem.

You can print it below to see the MRO sequence of single inheritance (FatBoss.mro).

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name):
        print('FatFather的init开始被调用')
        self.name = name
        print('调用FatFather类的name是%s' % self.name)
        print('FatFather的init调用结束')
# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby):
        print('胖子老板的类被调用啦!')
        self.hobby = hobby
        #FatFather.__init__(self,name)   # 直接调用父类的构造方法
        super().__init__(name)
        print("%s 的爱好是 %s" % (name, self.hobby))
def main():
    print("打印FatBoss类的MRO")
    print(FatBoss.__mro__)
    print()
    print("=========== 下面按照 MRO 顺序执行super方法 =============")
    fatboss = FatBoss("胖子老板", "打斗地主")

The above code uses FatBoss.mro to print out the inheritance calling sequence of the FatBoss class calculated by the C3 algorithm of the python parser.

Run as follows:

if __name__ == "__main__":
    main()
打印FatBoss类的MRO
(<class &#39;__main__.FatBoss&#39;>, <class &#39;__main__.FatFather&#39;>, <class &#39;object&#39;>)
=========== 下面按照 MRO 顺序执行super方法 =============
胖子老板的类被调用啦!
FatFather的init开始被调用
调用FatFather类的name是胖子老板
FatFather的init调用结束
胖子老板 的爱好是 打斗地主

From the above results (819fb8321e79eba8a7ae9f208b30d85a, 19021db2abd6a327a019e93aad66dcb4,

So what are the problems if there is multiple inheritance?

2.4 Multiple inheritance using super()

Suppose we write another class for the daughter of the fat boss and a class for the wife of the fat boss. At this time, the daughter needs to inherit both at the same time Category (fat boss category, fat boss wife category).

Because the fat boss has a hobby. The fat boss’s wife needs to work and do housework, so his daughter needs to help at the same time.

At this time, the daughter needs to inherit and use the methods of these two parent classes, so how to write it?

Let’s take a look at the implementation code:

# 胖子老板的父类
class FatFather(object):
    def __init__(self, name, *args, **kwargs):
        print()
        print("=============== 开始调用 FatFather  ========================")
        print(&#39;FatFather的init开始被调用&#39;)
        self.name = name
        print(&#39;调用FatFather类的name是%s&#39; % self.name)
        print(&#39;FatFather的init调用结束&#39;)
        print()
        print("=============== 结束调用 FatFather  ========================")
# 胖子老板类 继承 FatFather 类
class FatBoss(FatFather):
    def __init__(self, name, hobby, *args, **kwargs):
        print()
        print("=============== 开始调用 FatBoss  ========================")
        print(&#39;胖子老板的类被调用啦!&#39;)
        #super().__init__(name)
        ## 因为多继承传递的参数不一致,所以使用不定参数
        super().__init__(name, *args, **kwargs)
        print("%s 的爱好是 %s" % (name, hobby))
        print()
        print("=============== 结束调用 FatBoss  ========================")
# 胖子老板的老婆类 继承 FatFather类
class FatBossWife(FatFather):
    def __init__(self, name, housework, *args, **kwargs):
        print()
        print("=============== 开始调用 FatBossWife  ========================")
        print(&#39;胖子老板的老婆类被调用啦!要学会干家务&#39;)
        #super().__init__(name)
        ## 因为多继承传递的参数不一致,所以使用不定参数
        super().__init__(name, *args, **kwargs)
        print("%s 需要干的家务是 %s" % (name, housework))
        print()
        print("=============== 结束调用 FatBossWife  ========================")
# 胖子老板的女儿类 继承 FatBoss FatBossWife类
class FatBossGril(FatBoss, FatBossWife):
    def __init__(self, name, hobby, housework):
        print(&#39;胖子老板的女儿类被调用啦!要学会干家务,还要会帮胖子老板斗地主&#39;)
        super().__init__(name, hobby, housework)
def main():
    print("打印FatBossGril类的MRO")
    print(FatBossGril.__mro__)
    print()
    print("=========== 下面按照 MRO 顺序执行super方法 =============")
    gril = FatBossGril("胖子老板", "打斗地主", "拖地")

The running results are as follows:

if __name__ == "__main__":
    main()
打印FatBossGril类的MRO
(<class &#39;__main__.FatBossGril&#39;>, <class &#39;__main__.FatBoss&#39;>, <class &#39;__main__.FatBossWife&#39;>, 
<class &#39;__main__.FatFather&#39;>, <class &#39;object&#39;>)
=========== 下面按照 MRO 顺序执行super方法 =============
胖子老板的女儿类被调用啦!要学会干家务,还要会帮胖子老板斗地主
=============== 开始调用 FatBoss  ========================
胖子老板的类被调用啦!
=============== 开始调用 FatBossWife  ========================
胖子老板的老婆类被调用啦!要学会干家务
=============== 开始调用 FatFather  ========================
FatFather的init开始被调用
调用FatFather类的name是胖子老板
FatFather的init调用结束
=============== 结束调用 FatFather  ========================
胖子老板 需要干的家务是 拖地
=============== 结束调用 FatBossWife  ========================
胖子老板 的爱好是 打斗地主
=============== 结束调用 FatBoss  ========================

From the above running results, I deliberately give the start and end of the call to each class All are printed and marked, which can be seen.

The start call of each class starts according to the MRO sequence, and then ends one by one.

Also, because different parent classes need to be inherited, the parameters are not necessarily certain.

Therefore, all parent classes should add variable parameters *args and **kwargs, otherwise an error will be reported if the parameters do not correspond.

3. Notes

· Super().init has basically no difference in usage compared to class name.init in single inheritance.

·But there is a difference in multiple inheritance. The super method can ensure that each parent class method will only be executed once, while the method using the class name will cause the method to be executed multiple times. You can try writing a code to see the output.

·When using multiple inheritance, use the super method to pass parameters to the parent class. This should be due to the super algorithm in Python. All parameters must be passed, otherwise an error will be reported.

·When using single inheritance, if you use the super method, you cannot pass all the parameters. You can only pass the parameters required by the parent class method, otherwise an error will be reported.

·When using multiple inheritance, compared to using the class name.init method, you need to write all the parent classes once, but using the super method, you only need to write one sentence to execute everything The method of the parent class, which is also one of the reasons why multiple inheritance requires all parameters to be passed.

4. Exercise

What will be the output of the following code? Give your answer and explain.

class Parent(object):
    x = 1
class Child1(Parent):
    pass
class Child2(Parent):
    pass
print(Parent.x, Child1.x, Child2.x)
1 1 1
Child1.x = 2
print(Parent.x, Child1.x, Child2.x)
1 2 1

Note: Child1 already has his own x

Parent.x = 3
print(Parent.x, Child1.x, Child2.x)
3 2 3

The above is the detailed content of Detailed explanation of super() method in Python. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:jianshu.com. If there is any infringement, please contact admin@php.cn delete