Python 關於super 的 用法和原理(挖坑)

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原理(挖個坑先)

相關文章
相關標籤/搜索