super相關的介紹文章看了無數遍,每次看得都雲里霧裡的,沒過多久就忘了,只模糊知道跟MRO有關,但是稍微一複雜就不知道怎麼回事了,本篇文章主要記錄我對super的理解 1.粗暴簡單的理解 super的作用就是執父類的方法,雖然這句話不完全對,但是也差不多是那麼個意思了。 比如以單繼承為例 clas ...
super相關的介紹文章看了無數遍,每次看得都雲里霧裡的,沒過多久就忘了,只模糊知道跟MRO有關,但是稍微一複雜就不知道怎麼回事了,本篇文章主要記錄我對super的理解
1.粗暴簡單的理解
super的作用就是執父類的方法,雖然這句話不完全對,但是也差不多是那麼個意思了。
比如以單繼承為例
class A:
def p(self):
print('A')
class B(A):
def p(self):
super().p()
B().p()
>>> A
可以看到B().p()其實就是執行的A.p
2.萬能模板解題技巧
前面介紹的是最簡單的情況,那萬一複雜一點,比如多繼承的情況呢?這種情況我們只要知道 MRO 序列,無論super怎麼變化都不怕了,記住公式就完事了。MRO 序列簡單理解就是記錄了各個類繼承的先後順序,看下麵的例子就明白了
MRO 的介紹可以看這篇文章: https://python3-
cookbook.readthedocs.io/zh_CN/latest/c08/p07_calling_method_on_parent_class.html
我們看下麵的例子
class A:
def p(self):
print('A')
class B():
def p(self):
print('B')
class C(A,B):
def p(self):
print('C')
class D(C):
def p(self):
print('D')
a = A()
b = B()
c = C()
d = D()
四個類的MRO (可以通過查看__mro__
屬性獲得,例如A.__mro__
)) 分別是:
A: (A, object)
B: (B, object)
C: (C, A, B, object)
D: (D, C, A, B, object)
什麼意思呢,我們以A類為例,它的MRO順序是他自己和object,很好理解,因為python里一切都是對象,所以你可以看到四個類的終點都是object。那C類的 MRO 也好理解,第一個順序永遠是寄幾,然後按照代碼順序依次是 A,B,最後是object。
相信看到這你應該知道MRO是什麼意思了吧,那super是怎麼用的呢?
super本身其實就是一個類,super()其實就是這個類的實例化對象,它需要接收兩個參數 super(class, obj),它返回的是obj的MRO中class類的父類(可能有點繞,待會看後面的慄子就好懂了):
- class:就是類,這裡你可以是A,B,C或者D
- obj:就是一個具體的實例對象,即a,b,c,d。我們經常在類的
__init__
函數里看到super的身影,而且一般都是寫成這個樣子的super(className, self).__init__()
,self其實就是某個實例化的對象。
3.舉幾個慄子
看到這裡如果還是沒明白,咱們就多看幾個例子就完事了,建議你可以打開ipython輸入如下示例,可以更加直觀感受super:
慄子1
首先我們看看下麵的命令是什麼意思呢?
super(C, d).p()
前面我們說過super的作用是 返回的是obj的MRO中class類的父類,在這裡就表示返回的是d的MRO中C類的父類:
- 返回的是d的MRO:(D, C, A, B, object)
- 中C類的父類:A
那麼super(C, d)就等價於A,那麼super(C, d).p()會輸出A
慄子2
下麵代碼結果是什麼呢?
super(A, c).p()
返回的是c的MRO中A類的父類:
- 返回的是c的MRO:(C, A, B, object)
- 中C類的父類:B
所以最後的輸出是B
慄子.
註意:有的類裡面沒有super()
class A:
def p(self):
print('A')
class B(A):
def p(self):
super().p()
print('B')
class C(B):
def p(self):
print('C')
class D(C):
def p(self):
print('D')
d = D()
d.p()
這個很簡單,最後只會輸出D
那如果D類改成如下樣子呢?
class D(C):
def p(self):
super().p()
print('D')
很簡單,我們首先寫出D的MRO為 (D,C,B,A,object),預設狀態下,super()就表示前一個父類,這裡就是C類,那麼super().p()就會調用C的p函數,但是C.p里沒有調用super,所以就與A,B類無關了,那麼最終的輸出就是C,D
我們再看看最複雜的繼承情況
class A:
def p(self):
print('A')
#Python小白學習交流群:153708845
class B(A):
def p(self):
super().p()
print('B')
class C(B):
def p(self):
super().p()
print('C')
class D(C):
def p(self):
super().p()
print('D')
d = D()
d.p()
這裡建議你自己在紙上畫一下
MRO
所以最終結果是 A B C D
4.總結
對於無論有多少個super(class, obj),我們首先需要知道obj的MRO是什麼,然後找到class的前一個class是什麼就好了。