Python的Super方法
我們最常見的,可以說幾乎唯一能見到的使用super的形式是:
class SubClass(BaseClass):def method(self):super(SubClass, self).method()#do some thing here...其中,最常見的method()是__init__()
以前做過Java,剛剛接觸Python的繼承,的確感覺有點奇怪,有時候還能搞混。。。當然這還是因為Java是單繼承,只能用接口實現類似多繼承的方式,而Python就直接支持多繼承。
當我第一次見到這個super()的時候,我想說,這是啥啊?為什么Python的super看起來這么奇怪呢?
super直接指向父類的實例不就得了么?為什么非得搞兩個參數?
而且第一個參數還是自己的類名,而不是父類的類名!
既然是自己的類名你還費勁寫一遍干嘛,干脆省略不得了?
第二個參數為啥是self?既然是self你省略不得了?
還有,super()返回的是個啥玩意啊,為什么可以.method() ? 難道他返回了一個BaseClass的instance么?
今天就來解答這一連串的問題。
1)super直接指向父類的實例不就得了么?
首先是不能指向,因為子類實例里面根本就沒有一個父類實例,這跟java是不同的。詳細看這里。
其次是即便像我們想象的,子類實例里有一個叫super的指針,指向父類的實例(這個父類實例在子類實例生成的時候自動生成了,是子類實例的一個‘成員’)。
但是由于多繼承的存在,還是會有問題。這也是跟java不同,java不支持多繼承,java用接口的方式實現多繼承。
舉個例子:
當只存在單繼承的時候,一切很美好,就像java一樣:
你只需要在重寫方法的時候,用super去調用父類的方法,然后再做自己的事就可以了。
但是在多繼承的情況下,一切都不美好了:
當藝人展示自己能力的時候,他說,父親啊,你先展示自己的能力,然后我來!
但是父親是誰? 他有兩個父親! 總不能寫兩遍 super.展示自己 吧?
那么我們自然想到,給super搞一個參數不得了,指出super的是哪個父類。
比如 super(歌手).展示自己(),super(演員).展示自己(),好像一切又可以美好了:
先不說這種寫法多么的丑陋,重復了那么多無意義的、類似的行,單說這種方法根本就行不通。
我們看看如果某個藝人的實例調用了.展示能力() ,將會輸出什么:
我是人類,我能走路! 我是歌手,我能唱歌! 我是人類,我能走路! 我是演員,我能演戲! 我是藝人,我能代言廣告!有必要告訴大家兩遍你是個人類么?這要是一個又身兼了主持人的藝人,豈不是得大聲宣布三次自己是個人類??
這顯然是不好的。
而且,這只是其一,假設多說了幾遍自己是人類你也能忍,那么還有一種情況,更糟。
你比如說,藝人類沒有重寫 展現自己() 這個方法,當你用藝人的實例去調用 展現自己()的時候,將會發生啥?
不重寫的方法自動調用父類的,但是有兩個父類呀!調用哪個的呢?任意調用一個(比如按從左到右的順序)?
那么體現不出他另一個父類的特點呀!比如調用歌手類的,那只能體現出這個藝人既是個歌手,又是個人類,根本體現不出他是個演員!
兩個都調用?那萬一其中一個父類沒有這個方法呢?而且先調用哪個后調用哪個?按照左右順序么?
總之這樣很亂,編譯器表示壓力很大。
所以,python的super()用了兩個參數。
先寫在這里:
super(SubClass, self).method() 的意思是,根據self去找SubClass的‘父親’,然后調用這個‘父親’的method()
最最重點的地方來了:對于一個類來說,它的‘父類’到底是誰,取決于站在誰的角度去看。
‘父親’之所以加了引號,是因為‘父親’并不一定是上下級的繼承關系,很可能只是兄弟。比如上圖中歌手的‘父親’是‘演員’,但實際上他們是兄弟關系。
所以以后用‘下一個類’來代替這個帶引號的‘父親’。
總之,站在不同的實例的角度,看到的‘下一個類’是不同的。
這就是super()第二個參數————self 的意義。
如果是一個歌手實例調用的,那么self=歌手實例,super()將站在一個歌手的角度,去找歌手類的‘下一個類’,則會找到人類;
如果是一個藝人實例調用的,那么self=藝人實例,super()將站在一個藝人的角度,去找歌手類的‘下一個類’,則會找到演員。
代碼如下:
''' 遇到問題沒人解答?小編創建了一個Python學習交流QQ群:857662006 尋找有志同道合的小伙伴,互幫互助,群里還有不錯的視頻學習教程和PDF電子書! ''' class People(object):def show_my_power(self):print(u"I am a people, I can walk !")class Singer(People):def show_my_power(self):super(Singer, self).show_my_power()print(u"I am a singer, I can sing !")class Actor(People):def show_my_power(self):super(Actor, self).show_my_power()print(u"I am an actor, I can act !")class Artist(Singer, Actor):passif __name__ == "__main__":a = Artist()a.show_my_power()運行結果:
I am a people, I can walk ! I am an actor, I can act ! I am a singer, I can sing !這里需要注意:當一個類從多個類繼承的時候,按照從左到右的順序。
也就是說,站在藝人的角度,首先看到藝人類的‘下一個類’是歌手類,然后歌手類的‘下一個類’是演員類。
這是因為歌手寫在了左邊:Artist(Singer, Actor)
看一下上面代碼的執行過程吧:
由于 super() 絕大多數時候,都在咱們開篇說的這種情況下使用,即在類的定義語句塊內部寫:super(本類名,self)
所以 python3 做了個簡化,如果你在類定義的語句塊內寫一個不帶參數的super(),則相當于寫了 super(本類名,self)
因為 super() 不光可以用在類的定義內部,所以,這種方便僅在類定義體內部有效。
總結
以上是生活随笔為你收集整理的Python的Super方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python中type和object的关
- 下一篇: Python基础教程 os.walk()