python-學(xué)習(xí)-類中的 super()

super() 的入門使用

在類的繼承中疆股,如果重定義某個(gè)方法,該方法會覆蓋父類的同名方法倒槐,但有時(shí)旬痹,我們希望能同時(shí)實(shí)現(xiàn)父類的功能,這時(shí)讨越,我們就需要調(diào)用父類的方法了两残,可通過使用 super 來實(shí)現(xiàn),比如:

class Animal(object):
    def __init__(self, name):
        self.name = name
    def greet(self):
        print 'Hello, I am %s.' % self.name
 
class Dog(Animal):
    def greet(self):
        super(Dog, self).greet()   # Python3 可使用 super().greet()
        print 'WangWang...'

在上面把跨,Animal 是父類人弓,Dog 是子類,我們在 Dog 類重定義了 greet 方法着逐,為了能同時(shí)實(shí)現(xiàn)父類的功能崔赌,我們又調(diào)用了父類的方法,看下面的使用:

>>> dog = Dog('dog')
>>> dog.greet()
Hello, I am dog.
WangWang..

super 的一個(gè)最常見用法可以說是在子類中調(diào)用父類的初始化方法了耸别,比如:

class Base(object):
    def __init__(self, a, b):    # 創(chuàng)建實(shí)例時(shí)健芭,父類中有2個(gè)必須輸入的參數(shù)a,b
        self.a = a
        self.b = b
 
class A(Base):
    def __init__(self, a, b, c):   # 繼承時(shí),init后需要傳入的參數(shù)要大于下面init后的傳參數(shù)
        super(A, self).__init__(a, b)   
        self.c = c
# 錯(cuò)誤示范
class A(Base):
        def __init__(self,a,c):
                  super(A,self).__init__(a,b)   # 這里會報(bào)錯(cuò)秀姐,因?yàn)樯戏轿刺岬絙慈迈,不能寫入b
                  self.c = c
-----------------------------------------------
# 要寫入b,可以把 b 用值表示省有,而不是變量
In [115]: class Base(object):
     ...:     def __init__(self,a,b):
     ...:         self.a = a
     ...:         self.b = b
     ...:

In [116]: class AA(Base):
     ...:     def __init__(self,a,c):
     ...:         super(AA,self).__init__(a,100)
     ...:         self.c = c
     ...:

In [118]: test = AA(1,2)

In [119]: test.a
Out[119]: 1

In [120]: test.b    # 這里,b 就被默認(rèn)賦值100了痒留,就不會報(bào)錯(cuò)了
Out[120]: 100

In [121]: test.c
Out[121]: 2



深入 super( )

看了上面的使用谴麦,你可能會覺得 super 的使用很簡單,無非就是獲取了父類狭瞎,并調(diào)用父類的方法细移。其實(shí),在上面的情況下熊锭,super 獲得的類剛好是父類弧轧,但在其他情況就不一定了,super 其實(shí)和父類沒有實(shí)質(zhì)性的關(guān)聯(lián)碗殷。
讓我們看一個(gè)稍微復(fù)雜的例子精绎,涉及到多重繼承,代碼如下:

class Base(object):
    def __init__(self):
        print "enter Base"
        print "leave Base"
 
class A(Base):
    def __init__(self):
        print "enter A"
        super(A, self).__init__()
        print "leave A"
 
class B(Base):
    def __init__(self):
        print "enter B"
        super(B, self).__init__()
        print "leave B"
 
class C(A, B):
    def __init__(self):
        print "enter C"
        super(C, self).__init__()
        print "leave C"

其中锌妻,Base 是父類代乃,A, B 繼承自 Base, C 繼承自 A, B,它們的繼承關(guān)系如下:

 Base
      /  \
     /    \
    A      B
     \    /
      \  /
       C

現(xiàn)在仿粹,讓我們看一下使用:

>>> c = C()
enter C
enter A
enter B
enter Base
leave Base
leave B
leave A
leave C

如果你認(rèn)為 super 代表『調(diào)用父類的方法』搁吓,那你很可能會疑惑為什么 enter A 的下一句不是 enter Base 而是 enter B。原因是吭历,super 和父類沒有實(shí)質(zhì)性的關(guān)聯(lián)堕仔,現(xiàn)在讓我們搞清 super 是怎么運(yùn)作的。

MRO 列表

事實(shí)上晌区,對于你定義的每一個(gè)類摩骨,Python 會計(jì)算出一個(gè)方法解析順序(Method Resolution Order, MRO)列表,它代表了類繼承的順序朗若,我們可以使用下面的方式獲得某個(gè)類的 MRO 列表:

>>> C.mro()   # or C.__mro__ or C().__class__.mro()
[__main__.C, __main__.A, __main__.B, __main__.Base, object]

那這個(gè) MRO 列表的順序是怎么定的呢恼五,它是通過一個(gè)C3 線性化算法來實(shí)現(xiàn)的,這里我們就不去深究這個(gè)算法了哭懈,感興趣的讀者可以自己去了解一下灾馒,總的來說,一個(gè)類的 MRO 列表就是合并所有父類的 MRO 列表遣总,并遵循以下三條原則
1 . 子類永遠(yuǎn)在父類前面
2 . 如果有多個(gè)父類睬罗,會根據(jù)它們在列表中的順序被檢查
3 . 如果對下一個(gè)類存在兩個(gè)合法的選擇,選擇第一個(gè)父類

super 原理

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

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

獲取 inst 的 MRO 列表
查找 cls 在當(dāng)前 MRO 列表中的 index, 并返回它的下一個(gè)類琉预,即 mro[index + 1]
當(dāng)你使用 super(cls, inst) 時(shí)董饰,Python 會在 inst 的 MRO 列表上搜索 cls 的下一個(gè)類。

現(xiàn)在,讓我們回到前面的例子卒暂。

首先看類 C 的__init__方法:

super(C, self).__init__()

這里的 self 是當(dāng)前 C 的實(shí)例啄栓,self.__class__.mro() 結(jié)果是:

[__main__.C, __main__.A, __main__.B, __main__.Base, object]

可以看到,C 的下一個(gè)類是 A也祠,于是昙楚,跳到了 A 的__init__,這時(shí)會打印出 enter A诈嘿,并執(zhí)行下面一行代碼:

super(A, self).__init__()

注意堪旧,這里的 self 也是當(dāng)前 C 的實(shí)例,MRO 列表跟上面是一樣的奖亚,搜索 A 在 MRO 中的下一個(gè)類淳梦,發(fā)現(xiàn)是 B,于是昔字,跳到了 B 的__init__爆袍,這時(shí)會打印出 enter B,而不是 enter Base作郭。

整個(gè)過程還是比較清晰的陨囊,關(guān)鍵是要理解 super 的工作方式,而不是想當(dāng)然地認(rèn)為 super 調(diào)用了父類的方法夹攒。

小結(jié)

事實(shí)上蜘醋,super 和父類沒有實(shí)質(zhì)性的關(guān)聯(lián)。
super(cls, inst)獲得的是 clsinst的 MRO 列表中的下一個(gè)類芹助。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末堂湖,一起剝皮案震驚了整個(gè)濱河市闲先,隨后出現(xiàn)的幾起案子状土,更是在濱河造成了極大的恐慌,老刑警劉巖伺糠,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蒙谓,死亡現(xiàn)場離奇詭異,居然都是意外死亡训桶,警方通過查閱死者的電腦和手機(jī)累驮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舵揭,“玉大人谤专,你說我怎么就攤上這事∥缟” “怎么了置侍?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我蜡坊,道長杠输,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任秕衙,我火速辦了婚禮蠢甲,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘据忘。我一直安慰自己鹦牛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布勇吊。 她就那樣靜靜地躺著能岩,像睡著了一般。 火紅的嫁衣襯著肌膚如雪萧福。 梳的紋絲不亂的頭發(fā)上拉鹃,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天,我揣著相機(jī)與錄音鲫忍,去河邊找鬼膏燕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛悟民,可吹牛的內(nèi)容都是我干的坝辫。 我是一名探鬼主播,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼射亏,長吁一口氣:“原來是場噩夢啊……” “哼近忙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起智润,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤及舍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后窟绷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锯玛,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年兼蜈,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了攘残。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,673評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡为狸,死狀恐怖歼郭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辐棒,我是刑警寧澤病曾,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布姊途,位于F島的核電站,受9級特大地震影響知态,放射性物質(zhì)發(fā)生泄漏捷兰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一负敏、第九天 我趴在偏房一處隱蔽的房頂上張望贡茅。 院中可真熱鬧,春花似錦其做、人聲如沸顶考。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽驹沿。三九已至,卻和暖如春蹈胡,著一層夾襖步出監(jiān)牢的瞬間渊季,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工罚渐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留却汉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓荷并,卻偏偏與公主長得像合砂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子源织,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,562評論 2 349

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉翩伪,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,690評論 0 9
  • 在類的繼承中,如果重定義某個(gè)方法谈息,該方法會覆蓋父類的同名方法缘屹,但有時(shí),我們希望能同時(shí)實(shí)現(xiàn)父類的功能黎茎,這時(shí)囊颅,我們就需...
    旅行的木訥閱讀 233評論 0 0
  • 我們常常會聽說 Objective-C 是一門動(dòng)態(tài)語言当悔,那么這個(gè)「動(dòng)態(tài)」表現(xiàn)在哪呢傅瞻?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,182評論 0 7
  • 今天真是值得紀(jì)念的一天。 今天考科目2盲憎,滿分通過嗅骄,值得慶祝。 今天我的體重在吃了四頓飯之后達(dá)到了70.4KG饼疙,有史...
    白夜夢想家閱讀 135評論 0 2
  • 大家可能會誤解《中庸》的「喜怒哀樂之未發(fā)医窿,謂之中。發(fā)而中節(jié)炊林,謂之和」的含義姥卢,以為,作為一個(gè)心智玩家渣聚,在日常生活独榴、工...
    心智玩家的簡書閱讀 771評論 16 11