首先提一下,经典类和新式类。在Python2中,如果定义类的方式是 class MyClass: 那么该类叫做经典类,如果定义类的方式为class MyClass(object): 那么该类为新式类。在Python3中,上面两种方式定义出来的类都叫新式类。本文是基于新式类来进行讲解的。
正文:
Python 中的 super() 是用于调用父类(或父类的父类...)方法的 函数,主要用于多继承,单继承问题不大。下面是一个多继承实例,继承关系为菱形继承, 仔细观察下面三个实例:
1 #coding=utf-8 2 #实例一: 3 class A(object): 4 def __init__(self): 5 print("class ---- A ----") 6 7 class B(A): 8 def __init__(self): 9 print("class ---- B ----") 10 super(B, self).__init__() 11 12 class C(A): 13 def __init__(self): 14 print("class ---- C ----") 15 super(C, self).__init__() 16 17 class D(B, C): 18 def __init__(self): 19 print("class ---- D ----") 20 super(D, self).__init__() 21 22 d = D() 23 ''' 24 #输出结果: 25 class ---- D ---- 26 class ---- B ---- 27 class ---- C ---- 28 class ---- A ---- 29 '''
1 #coding=utf-8 2 #实例二: 更改一下类D的super函数: 3 class D(B, C): 4 def __init__(self): 5 print("class ---- D ----") 6 super(B, self).__init__() 7 8 d = D() 9 ''' 10 #输出结果: 11 class ---- D ---- 12 class ---- C ---- 13 class ---- A ---- 14 '''
1 # 实例三: 再更改一下类D的super函数: 2 class D(B, C): 3 def __init__(self): 4 print("class ---- D ----") 5 super(C, self).__init__() 6 7 d = D() 8 ''' 9 # 输出结果: 10 class ---- D ---- 11 class ---- A ---- 12 '''
如果你认为 super() 函数就是 调用父类的方法,那你可能想不通后面两个实例。原因是,super() 和父类没有实质性的关联。如果想要搞懂super() 函数的运行原理,那一定要先搞懂 __mro__ 属性, __mro__ 是Method Resolution Order,中文方法解析顺序。单继承中super() 函数使用比较简单的原因 也是因为 __mro__ 比较简单,多继承的__mro__就稍微复杂了,总之 __mro__的目的就是 按照一定顺序,保证父类的函数只调用一次。
我们来先打印一下 它的属性值,再次修改类D的super函数:
1 class D(B, C): 2 def __init__(self): 3 print(D.__mro__) 4 print("class ---- D ----") 5 super(D, self).__init__() 6 7 d = D() 8 9 ''' 10 #输出结果: 11 (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>) 12 class ---- D ---- 13 class ---- B ---- 14 class ---- C ---- 15 class ---- A ---- 16 '''
从打印结果可以看出,__mro__是一个元组,类D的__mro__顺序是 D -> B -> C -> A -> object。敲黑板(重点):如果在类D中 调用super()函数时 传入的第一个参数是D,那么super() 函数就会在__mro__ 里从D的上一级开始查找,它的上一级是B, 那么super(D, self).__init__() 就调用B的__init__()函数,B的__init__()函数里又调用了B的super()函数,super(B, self).__init__(), 那就从B的上一级再开始查找,B的上一级是C, 以此类推,然后是A,最后是object。于是实例一也就解释清楚了。
实例二中 类D的super() 方法第一个参数传入的是 B ,那么根据__mro__顺序开始查找,B的上一级是C,C的上一级是A,所以实例二的打印顺序是 D - > C -> A
实例三也就不难解释了。
最后再讲一下 super()函数的参数,该函数需要两个参数,第一个是类名,第二个一般都是self,但偶尔也有cls的情况,在:Python 3 可以使用直接使用 super() .xxx 代替 super(Class, self).xxx, 比如:
1 class D(B, C): 2 def __init__(self): 3 print(D.__mro__) 4 print("class ---- D ----") 5 super().__init__() 6 d = D() 7 ''' 8 #输出结果: 9 (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>) 10 class ---- D ---- 11 class ---- B ---- 12 class ---- C ---- 13 class ---- A ---- 14 '''
再回到文章的开始,谈一下经典类和新式类:
经典类的MRO方法是采用 从左至右的深度优先遍历 算法,重复留前者
按照深度遍历,其顺序为 [D, B, A, object, C, A, object],重复者只保留前面一个,因此变为 [D, B, A, object, C]
新式类的MRO方法是采用 从左至右的深度优先遍历 的算法,重复留后者
按照深度遍历,其顺序为 [D, B, A, object, C, A, object],重复者只保留后面一个,因此变为 [D, B, C, A, object]
————————————————
版权声明:本文为CSDN博主「芝士锅」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wanzew/article/details/106993425
标签:__,Python,self,----,init,详解,super,class From: https://www.cnblogs.com/sunzhiqi/p/16985677.html