1、前言算法
Python 面向對象中有繼承這個概念,初學時感受很牛逼,裏面也有個super類,常常見到,最近作一些題纔算是理解了。特意記錄分享給後來研究的小夥伴,畢竟如今小學生都開始學了(滑稽臉)函數
2、代碼spa
直接上乾貨,能把下面一個問題全答對,後面就不用看了。設計
class A(): def go(self): print ("go A go!") def stop(self): print ("stop A stop!") def pause(self): raise Exception("Not Implemented") class B(A): def go(self): super(B, self).go() print ("go B go!") class C(A): def go(self): super(C, self).go() print ("go C go!") def stop(self): super(C, self).stop() print ("stop C stop!") class D(B,C): def go(self): super(D, self).go() print ("go D go!") def stop(self): super(D, self).stop() print ("stop D stop!") def pause(self): print ("wait D wait!") class E(B,C): pass a = A() b = B() c = C() d = D() e = E() # 說明下列代碼的輸出結果 a.go() print('--------') b.go() print('--------') c.go() print('--------') d.go() print('--------') e.go() print('--------') a.stop() print('--------') b.stop() print('--------') c.stop() print('--------') d.stop() print('--------') e.stop() print(D.mro()) a.pause() b.pause() c.pause() d.pause() e.pause()
固然,直接運行就有答案了,仍是要仔細想一下,反正看到我第一次跑出的結果的時候,我都不敢相信本身的眼睛。code
step1:orm
幾個概念:對象
繼承的功能:父類的代碼重用blog
多態的功能:同一方法對不一樣類型的對象會有相應的結果繼承
開閉原則:對擴展開放,對修改封閉it
super類功能:新式類實現廣度優先的不重複的調用父類,解決了鑽石繼承(多繼承)的難題
step2:
super實現原理:經過c3算法,生成mro(method resolution order)列表,根據列表中元素順序查詢調用
新式類調用順序爲廣度優先,舊式類爲深度優先
step3:
我的理解:
1.調用了父類的方法,出入的是子類的實例對象
2.新式類子類(A,B),A就在B以前
3.super相似於嵌套的一種設計,當代碼執行到super實例化後,先去找同級父類,若沒有其他父類,再執行自身父類,再往下走,
簡潔點的三個原則就是:
子類在父類前,全部類不重複調用,從左到右
理解了以上的說法,題目就沒問題了。
也不用跑了,答案以下:
a.go()# go A go! b.go()# go A go!# go B go! c.go()# go A go!# go C go! d.go()# go A go!# go C go!# go B go!# go D go! e.go()# go A go!# go C go!# go B go! a.stop()# stop A stop! b.stop()# stop A stop! c.stop()# stop A stop!# stop C stop! d.stop()# stop A stop!# stop C stop!# stop D stop! e.stop()# stop A stop! a.pause()# ... Exception: Not Implemented b.pause()# ... Exception: Not Implemented c.pause()# ... Exception: Not Implemented d.pause()# wait D wait! e.pause()# ...Exception: Not Implemented
看了答案,其實還有一點,父類拋異常的狀況,若是子類有不拋異常的方法,異常就不拋出了,這個設計也會頗有用。
這裏就中間一個A,C,B,D的和網上常見的不太同樣,促使我仔細研究了一下,其實就是我的理解第三條。
補充:
Python2 和Python3在這個問題上的差異
Python2 沒有默認繼承object
Python3 默認所有繼承object類,都是新式類
Python2super調用 super(開始類名,self).函數名()
Python3 super().函數名()
關於調用父類函數傳入子類實例的栗子舉一個:
class A: def __init__(self): self.n = 2 def add(self, m): print('self is {0} @A.add'.format(self)) self.n += m class B(A): def __init__(self): self.n = 3 def add(self, m): print('self is {0} @B.add'.format(self)) super().add(m) print('newb') self.n += 3 class C(A): def __init__(self): self.n = 4 def add(self, m): print('self is {0} @C.add'.format(self)) super().add(m) print('newc') self.n += 4 class D(B, C): def __init__(self): self.n = 5 def add(self, m): print('self is {0} @D.add'.format(self)) super().add(m) self.n += 5 d = D() d.add(2) print(d.n)
夜深了,暫時會這麼多就寫這麼多,有空研究c3原理(挖個坑先)