在看python高級(jí)編程這本書的時(shí)候尚猿,在講到super的時(shí)候,產(chǎn)生了一些疑惑,super在python中的用法跟其他的語(yǔ)言有一些不一樣的地方拔鹰,在網(wǎng)上找了一些資料,發(fā)現(xiàn)基本上很少有文章能把我的疑惑講明白贵涵,其中這篇文章最有價(jià)值的地方是它講解了我們平時(shí)對(duì)super的正確使用方法列肢。
首先看一段程序:
class A:
def __init__(self):
print("A", end=" ")
super().__init__()
class E:
def __init__(self):
print("E", end=" ")
super().__init__()
class B(E):
def __init__(self):
print("B", end=" ")
super().__init__()
class D:
def __init__(self):
print("D", end=" ")
super().__init__()
class C(A, B, D):
def __init__(self):
print("C", end=" ")
A.__init__(self)
D.__init__(self)
B.__init__(self)
print("MRO:", [x.__name__ for x in C.__mro__])
print(C())
這段程序的打印結(jié)果是:
MRO: ['C', 'A', 'B', 'E', 'D', 'object']
C A B E D D B E D <__main__.C object at 0x1040340b8>
這段程序可以簡(jiǎn)單演示super()的用法,比較簡(jiǎn)單的概念是mro宾茂,它告訴我們某個(gè)類的繼承鏈信息瓷马,生成這個(gè)鏈的原則有兩條:
- 在繼承關(guān)系中,所有的子類都在父類前邊
- 如果出現(xiàn)沖突跨晴,則按照其base排序
要想理解上邊程序的打印結(jié)果欧聘,只需要知道super()其實(shí)它相當(dāng)于super(cls, self),知道了這一點(diǎn)答案就很清晰了
當(dāng)執(zhí)行A.__init__(self)
這行代碼的時(shí)候端盆,self指向了c實(shí)例對(duì)象怀骤,然后打印出A,當(dāng)調(diào)用super().__init__()
這行代碼的時(shí)候爱谁,實(shí)際相當(dāng)于super(A, self).__init__()
的調(diào)用晒喷, super(A, self)
的會(huì)在self.mro中查找排在A后邊的類,這樣就實(shí)現(xiàn)了繼承鏈的調(diào)用了访敌。
其實(shí)到了這里凉敲,我們基本上能猜到super()的實(shí)現(xiàn)原理了,雖然看上去它像沒傳入?yún)?shù)一樣,其實(shí)不然爷抓,如果我們改變參數(shù)势决,找到的父類是不同的。
我們把上邊代碼中的A稍微改變一下:
class A:
def __init__(self):
print("A", end=" ")
super(D, self).__init__()
那么在這里super(D, self)
獲取的就是object了蓝撇,因此打印結(jié)果是:
MRO: ['C', 'A', 'B', 'E', 'D', 'object']
C A D B E D <__main__.C object at 0x1040340b8>
super()具有運(yùn)行時(shí)特性果复,也就是說它的結(jié)果是動(dòng)態(tài)計(jì)算出來的,利用這一點(diǎn)可以寫出擴(kuò)展性比較好的程序渤昌,同時(shí)虽抄,從編程語(yǔ)義也更符合生活習(xí)慣。目前能夠總結(jié)的就是這樣独柑。