python类的继承super方法_Python类的继承super相关原理解析
看了網(wǎng)上許多關(guān)于super、mro、C3的介紹感覺(jué)沒(méi)有一份很容易初學(xué)者理解的文檔,直接看C3算法的話,比較難理解,也沒(méi)必要,如果掌握一套規(guī)律的話,會(huì)輕松許多。我將網(wǎng)上這些博主的文章進(jìn)行一個(gè)梳理總結(jié),最后形成一套實(shí)用的關(guān)于super、mro、C3的理解介紹。
1、super
super()是一種將子類(lèi)與父類(lèi)聯(lián)系起來(lái)的一種方法,子類(lèi)通過(guò)繼承父類(lèi),可以使用父類(lèi)的方法和屬性,也可以自己定義屬于自己的方法和屬性。super方法主要用在多繼承中,在單繼承時(shí)直接調(diào)用父類(lèi)方法即可
下面這個(gè)是SGD源碼的一部分,根據(jù)這份源碼,
class SGD(Optimizer):
def __init__(self, params, lr=required, momentum=0, dampening=0,
weight_decay=0, nesterov=False):
defaults = dict(lr=lr, momentum=momentum, dampening=dampening,
weight_decay=weight_decay, nesterov=nesterov)
if nesterov and (momentum <= 0 or dampening != 0):
raise ValueError("Nesterov momentum requires a momentum and zero dampening")
super(SGD, self).__init__(params, defaults)
def __setstate__(self, state):
super(SGD, self).__setstate__(state)
for group in self.param_groups:
group.setdefault('nesterov', False)
這是SGD類(lèi)中的代碼
有2點(diǎn)需要補(bǔ)充說(shuō)明:
1、super聯(lián)系父類(lèi)的時(shí)候,需要調(diào)用父類(lèi)的方法,包括所帶的形參寫(xiě)完整,子類(lèi)不夠的形參需要額外加上
2、super聯(lián)系父類(lèi)的時(shí)候,不只是可以調(diào)用__init__,而且還可以調(diào)用父類(lèi)其他的方法
3、python3可以寫(xiě)成super().__init__()這種寫(xiě)法了。
4、類(lèi)都默認(rèn)繼承object類(lèi)
另外,在super的使用過(guò)程中,還需要注意初始化對(duì)繼承的影響:
1、子類(lèi)繼承父類(lèi),但不執(zhí)行__init__方法,那么會(huì)自動(dòng)繼承父類(lèi)屬性。
2、子類(lèi)繼承父類(lèi),執(zhí)行了__init__方法,且不調(diào)用super初始化父類(lèi)構(gòu)造函數(shù),那么子類(lèi)不會(huì)自動(dòng)繼承父類(lèi)屬性。
3、子類(lèi)繼承父類(lèi),執(zhí)行了__init__方法,且調(diào)用了super初始化了父類(lèi)的構(gòu)造函數(shù),那么子類(lèi)會(huì)繼承父類(lèi)屬性。
2、mro
Python的MRO,方法解析順序,即在調(diào)用方法時(shí),會(huì)對(duì)當(dāng)前類(lèi)以及所有的基類(lèi)進(jìn)行一個(gè)搜索,以確定該方法之所在,而這個(gè)搜索的順序就是MRO。然后python會(huì)按照這個(gè)順序去執(zhí)行類(lèi)之間的調(diào)用問(wèn)題。
直接上例子
class A1():
def __init__(self):
print('A1')
super().__init__()
class A2():
def __init__(self):
print('A2')
super().__init__()
class A3():
def __init__(self):
print('A3')
super().__init__()
class B1(A1, A2):
def __init__(self):
print('B1')
super().__init__()
class B2(A2):
def __init__(self):
print('B2')
super().__init__()
class B3(A2, A3):
def __init__(self):
print('B3')
super().__init__()
class C1(B1):
def __init__(self):
print('C1')
super().__init__()
class C2(B1, B2):
def __init__(self):
print('C2')
super().__init__()
class C3(B2, B3):
def __init__(self):
print('C3')
super().__init__()
class D(C1, C2, C3):
def __init__(self):
print('D')
super().__init__()
d = D()
print(D.__mro__)
輸出如下:
(, , , , , , , , , , )
那么這個(gè)程序是按怎么個(gè)順序依次去執(zhí)行那些方法呢,就是按照MRO中的順序。
那么這個(gè)順序如何自己手寫(xiě)出來(lái)呢?這就是C3算法,用于計(jì)算出MRO,得出執(zhí)行順序
3、c3算法
但是我在這里想告訴大家如何根據(jù)C3算法找出規(guī)律,從而自己寫(xiě)出順序
還是上手例子,根據(jù)上面這個(gè)圖,我們可以列出下面這個(gè)表,這個(gè)表示網(wǎng)上一個(gè)博主做的,可以說(shuō)做出這張表就是做出了答案,那這張表“實(shí)際取出的類(lèi)”怎么推出來(lái)的呢?我拿過(guò)來(lái)提煉出一些比較直接的規(guī)律
規(guī)律1:預(yù)查找父類(lèi)按左邊優(yōu)先原則,比如第一行,當(dāng)前類(lèi)D的預(yù)查找父類(lèi)選最左邊的C1,而不是C2、C3。
規(guī)律2:當(dāng)“預(yù)查找父類(lèi)是否還有其他子類(lèi)?同時(shí)又是最底層查找類(lèi)的父類(lèi)或父父類(lèi)、父父父...類(lèi)”沒(méi)有的時(shí)候,直接選取預(yù)查找父類(lèi)作為答案。當(dāng)這項(xiàng)有類(lèi)的時(shí)候,若“最底層的未查找父類(lèi)”還有,則優(yōu)先選它,若沒(méi)有了,則選取這項(xiàng)類(lèi)作為答案。
規(guī)律3:當(dāng)預(yù)查找父類(lèi)是object,只要最底層的未查找父類(lèi)還有,就選這個(gè)最底層的未查找父類(lèi)。若沒(méi)有,則“預(yù)查找父類(lèi)是否還有其他子類(lèi)?同時(shí)又是最底層查找類(lèi)的父類(lèi)或父父類(lèi)、父父父...類(lèi)”有類(lèi)的時(shí)候,就選這個(gè)類(lèi),沒(méi)有的話,答案就是object
另外,
如何去畫(huà)圖:
1、子類(lèi)永遠(yuǎn)畫(huà)在父類(lèi)的下面,并用有向箭頭指向父類(lèi)
2、遇到多繼承則按代碼中繼承列表的順序從左往右寫(xiě)。如果有多個(gè)子類(lèi)繼承了同一個(gè)父類(lèi),那么這個(gè)父類(lèi)則放在它能夠出現(xiàn)的所有位置中最左的位置。需遵循圖里面的廣度優(yōu)先原則進(jìn)行遍歷(在廣度優(yōu)先原則的前提下又優(yōu)先遍歷左邊的):
練習(xí):
下面這個(gè)是網(wǎng)上的一份代碼,看懂上面的規(guī)律以及如何畫(huà)有向圖之后,就可以順利得出MRO的值了
class A:
def __init__(self):
print('A')
class B(A):
def __init__(self):
print('B')
super().__init__()
class C(A):
def __init__(self):
print('C')
super().__init__()
class D(A):
def __init__(self):
print('D')
super().__init__()
class E(B, C):
def __init__(self):
print('E')
super().__init__()
class F(C, D):
def __init__(self):
print('F')
super().__init__()
class G(E, F):
def __init__(self):
print('G')
super().__init__()
首先,畫(huà)圖
然后列表
當(dāng)前類(lèi)最底層未查找的父類(lèi)預(yù)查找的父類(lèi)預(yù)查找父類(lèi)是否為object預(yù)查找父類(lèi)是否有其他子類(lèi),同時(shí)又是最底層查找類(lèi)的父類(lèi)、父父類(lèi)實(shí)際取出的類(lèi)GE、FEnonoEEFBnonoBBFAno有,CFFnoCnonoCCnoAno有,DDDnoAnonoAAnoobjectyesnoobject
答案:
mro:GEBFC
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
總結(jié)
以上是生活随笔為你收集整理的python类的继承super方法_Python类的继承super相关原理解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: svn 分支上新增文件合并发生冲突_SV
- 下一篇: dubbo mysql_dubbo系列