python里 super類的工作原理詳解
super 的工作原理如下:
def super(cls, inst): mro = inst.__class__.mro() return mro[mro.index(cls) + 1]
其中,cls 代表類,inst 代表實例,上面的代碼做了兩件事:
- 獲取 inst 的 MRO 列表
- 查找 cls 在當(dāng)前 MRO 列表中的 index, 并返回它的下一個類,即 mro[index + 1]
當(dāng)你使用 super(cls, inst) 時,Python 會在 inst 的 MRO 列表上搜索 cls 的下一個類。
下面看一個例子:
class A:
def __init__(self):
self.n = 2
def add(self, m):
print('\n\nself is {0} @A.add'.format(self))
self.n += m
class B(A):
def __init__(self):
self.n = 3
def add(self, m):
print('\n\nself is {0} @B.add'.format(self))
super(B, self).add(m)
self.n += 3
class C(A):
def __init__(self):
self.n = 4
def add(self, m):
print('\n\nself is {0} @C.add'.format(self))
super(C, self).add(m)
self.n += 4
class D(B, C):
def __init__(self):
self.n = 5
def add(self, m):
print('\n\nself is {0} @D.add'.format(self))
print(super(D, self).__self__)
print(super(D, self).__thisclass__)
super(D, self).add(m)
self.n += 5
if __name__ == '__main__':
print(D.mro())
d = D()
d.add(2) # 等于是: D.add(d, 2)
print(d.n)
結(jié)果是:
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] <__main__.D object at 0x101ef16d8> self is <__main__.D object at 0x101ef16d8> @D.add <__main__.D object at 0x101ef16d8> <class '__main__.D'> self is <__main__.D object at 0x101ef16d8> @B.add self is <__main__.D object at 0x101ef16d8> @C.add self is <__main__.D object at 0x101ef16d8> @A.add 19
來通過這個結(jié)果具體說幾點細(xì)節(jié):
print(D.mro()) 首先打印出 D類的 mro 列表:[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>] 。 這個非常好理解。
然后我們通過d = D()創(chuàng)建一個D類的實例: <__main__.D object at 0x101ef16d8>; 為了方便, 我們就把這個實例object at 0x101ef16d8 叫做 “小明” 吧
召喚d.add(2) 這個函數(shù)的時候,D類中add函數(shù)的self實際上就是這個剛被創(chuàng)建的小明同學(xué)object at 0x101ef16d8.
那么接下來呢,super(D, self) 就是在 object at 0x101ef16d8 的mro列表中,在小明的MRO列表中, 找到 class D(D類)的下一個 class(類), 這里也就是 class B (B類) 。
注意 mro列表里 <class '__main__.D'> 的下一個是 <class '__main__.B'>
每一個 add 函數(shù)打印的都是 self is <__main__.D object at 0x101ef16d8>, 往上追溯的過程中,無論到了哪一級,self始終都是最初創(chuàng)建的那個 D類的實例。
這是為什么呢?
注意看 print(super(D, self).__self__) 那一行返還的輸出:<__main__.D object at 0x101ef16d8> .
哦哦?! 這他媽的不是小明嗎?
也就是說, super()雖然找到的是B類,召喚的是B類的 add()函數(shù),但它的self仍然是最開始創(chuàng)建的D類實例(我們的 小明同學(xué)),而且召喚add()這個函數(shù)時,仍然是把這樣的一個self傳給了 class B 的 add()函數(shù)。
我們的 “小明”, 就這樣被一次次的往上傳導(dǎo)到了每一級的 add() 函數(shù)中, 于是每一級打印的都是:
self is <__main__.D object at 0x101ef16d8> 或者說: self is 小明
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
詳解Python圖像形態(tài)學(xué)處理(開運算,閉運算,梯度運算)
數(shù)學(xué)形態(tài)學(xué)(Mathematical Morphology)是一種應(yīng)用于圖像處理和模式識別領(lǐng)域的新方法。本文將為大家介紹Python圖像形態(tài)學(xué)處理中的開運算、閉運算和梯度運算,感興趣的可以了解一下2022-06-06
Python控制自己的手機攝像頭拍照并自動發(fā)送到郵箱案例講解
這篇文章主要介紹了Python控制自己的手機攝像頭拍照,并把照片自動發(fā)送到郵箱,大概思路是通過opencv調(diào)用攝像頭拍照保存圖像本地用email庫構(gòu)造郵件內(nèi)容,保存的圖像以附件形式插入郵件內(nèi)容用smtplib庫發(fā)送郵件到指定郵箱,需要的朋友可以參考下2022-04-04
pandas實現(xiàn)處理TB級別的數(shù)據(jù)
這篇文章主要介紹了pandas實現(xiàn)處理TB級別的數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-04-04
用Python從0開始實現(xiàn)一個中文拼音輸入法的思路詳解
中文輸入法是一個歷史悠久的問題,但也實在是個繁瑣的活,不知道這是不是網(wǎng)上很少有人分享中文拼音輸入法的原因,接下來通過本文給大家分享使用Python從0開始實現(xiàn)一個中文拼音輸入法,需要的朋友可以參考下2019-07-07
python用PyInstaller打包成windows可執(zhí)行的exe(細(xì)致版)
PyInstaller的基本功能是將Python腳本打包成可執(zhí)行文件,這意味著用戶無需安裝Python環(huán)境,就能運行打包后的程序,這篇文章主要介紹了python如何用PyInstaller打包成windows可執(zhí)行exe的相關(guān)資料,需要的朋友可以參考下2025-04-04

