日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

super函数没有那么简单-super原理剖析

發(fā)布時(shí)間:2024/9/5 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 super函数没有那么简单-super原理剖析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

開始之前,先出一道題:

1 #super函數(shù)探討 2 class A(object): 3 def __init__(self): 4 print 'A.__init__' 5 6 class B(A): 7 def __init__(self): 8 super(B, self).__init__() 9 print 'B.__init__' 10 11 class C(A): 12 def __init__(self): 13 super(C, self).__init__() 14 print 'C.__init__' 15 16 class D(B, C): 17 def __init__(self): 18 super(D, self).__init__() 19 print 'D.__init__' 20 21 d = D() View Code

上面的運(yùn)行結(jié)果是什么?

是下面的結(jié)果嗎?

A.__init__ B.__init__ D.__init__

正確答案:

A.__init__ C.__init__ B.__init__ D.__init__

有沒有疑惑?super()函數(shù)不是調(diào)用指定類的父類的方法嗎!打印了A.__init__下一句為什么是C.__init__呢?

根本原因是:

super?和父類沒有實(shí)質(zhì)性的關(guān)聯(lián)

首先,我們知道新式類采用廣度優(yōu)先算法,我們來看一下上面的繼承關(guān)系:

那么,Python是如何實(shí)現(xiàn)繼承的,繼承順序又是由誰決定的呢? 對(duì)于你定義的每一個(gè)類而已,Python會(huì)計(jì)算出一個(gè)所謂的方法解析順序(MRO Method?Resolution Order)列表。類的繼承順序就是由這個(gè)MRO決定的

MRO通過class.__mro__來查看,我們來打印一下上面例子中的MRO:

print D.__mro__ (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)

注意__mro__是類的屬性,實(shí)例沒有該屬性

這個(gè)MRO列表就是一個(gè)簡(jiǎn)單的所有基類的線性順序表。為了實(shí)現(xiàn)繼承,Python會(huì)在MRO列表上從左到右開始查找基類,直到找到第一個(gè)匹配這個(gè)屬性的類為止。

而這個(gè)MRO列表的構(gòu)造是通過一個(gè)C3線性化算法來實(shí)現(xiàn)的。 它實(shí)際上就是合并所有父類的MRO列表并遵循如下三條準(zhǔn)則:

1)子類會(huì)先于父類被檢查

2)多個(gè)父類會(huì)根據(jù)它們?cè)诹斜碇械捻樞虮粰z查

3)如果對(duì)下一個(gè)類存在兩個(gè)合法的選擇,選擇第一個(gè)父類

好像還是沒明白為什么例子中,打印了A.__init__下一句為什么是C.__init__呢?

我們使用一個(gè)函數(shù)來解釋一下super的原理:

def super(cls, inst):mro = inst.__class__.mro()return mro[mro.index(cls) + 1]

其中,cls 代表類,inst 代表實(shí)例,上面的代碼做了兩件事:

1)獲取 inst 的 MRO 列表

2)查找 cls 在當(dāng)前 MRO 列表中的 index, 并返回它的下一個(gè)類,即 mro[index + 1]

當(dāng)你使用?super(cls, inst)?時(shí),Python 會(huì)在 inst 的 MRO 列表上搜索 cls 的下一個(gè)類。

是不是有一種豁然開朗的趕腳!讓我們回到例子中,這里我畫出了整個(gè)流程;

從上面的流程圖就可以看出打印的順序是對(duì)的!

了解了super的原理,那么也就可以理解下面這段有趣的代碼了:

1)執(zhí)行下面代碼

1 class A(object): 2 def go(self): 3 print 'A go' 4 super(A, self).go() 5 6 a = A() 7 a.go() View Code

會(huì)報(bào)錯(cuò):

AttributeError: 'super' object has no attribute 'go'

2)執(zhí)行下面代碼:

1 class A(object): 2 def go(self): 3 print 'A go' 4 super(A, self).go() 5 6 class B(object): 7 def go(self): 8 print 'B go' 9 10 class C(A, B): 11 pass 12 13 c = C() 14 c.go() View Code

不會(huì)報(bào)錯(cuò),結(jié)果為:

A go B go

充分說明了super?和父類沒有實(shí)質(zhì)性的關(guān)聯(lián)

另外,我們想出了super以外,還有一種直接調(diào)用父類方法的方法,如下:

1 #super函數(shù)探討 2 class A(object): 3 def __init__(self): 4 print 'A.__init__' 5 6 class B(A): 7 def __init__(self): 8 # super(B, self).__init__() 9 A.__init__(self) 10 print 'B.__init__' 11 12 class C(A): 13 def __init__(self): 14 # super(C, self).__init__() 15 A.__init__(self) 16 print 'C.__init__' 17 18 class D(B, C): 19 def __init__(self): 20 # super(D, self).__init__() 21 B.__init__(self) 22 C.__init__(self) 23 print 'D.__init__' 24 25 d = D() View Code

為什么不用這種方法呢?我們運(yùn)行一下,看一下,結(jié)果為:

A.__init__ B.__init__ A.__init__ C.__init__ D.__init__

很明顯,A的構(gòu)造函數(shù)運(yùn)行了兩次,這不是我們所希望的;所以還是用super吧!

轉(zhuǎn)載于:https://www.cnblogs.com/deeper/p/7453759.html

與50位技術(shù)專家面對(duì)面20年技術(shù)見證,附贈(zèng)技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的super函数没有那么简单-super原理剖析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。