MRO(Method resolution order)是python用來解析方法呼叫順序的,mro中記錄了一個類的所有基類的類型別序列,super不是簡單地呼叫基類的方法,而是按照MRO中的順序來呼叫類的方法。
使用super()時,應該在所有類中使用,否則就可能發生有的類建構函式沒有呼叫的情況。
1 #!/usr/bin/python 2 # -*- coding: utf-8 -*- 3 class A(object): 4 def __init__(self): 5 print 'A __init__' 6 super(A, self).__init__() 7 print 'leave A' 8 class C(object): 9 def __init__(self): 10 print 'C __init__' 11 super(C, self).__init__() 12 print 'leave C' 13 class B(A,C): 14 def __init__(self): 15 print 'B __init__' 16 super(B, self).__init__() 17 print 'leave B' 18 class D(B): 19 def __init__(self): 20 print 'D __init__' 21 super(D, self).__init__() 22 print 'leave D' 23 if __name__ == '__main__': 24 D() 25 26 輸出為: 27 D __init__ 28 B __init__ 29 A __init__ 30 C __init__ 31 leave C 32 leave A 33 leave B 34 leave D
編譯過程:super(D,self)查詢D的父類,根據廣度優先演算法依次查詢super(類名,self)的父類。
順便說一下 經典類和新式類的區別?
(1)在python2.x中,從object繼承得來的類稱為新式類(如class A(object))不從object繼承得來的類稱為經典類(如class A())
(2) 新式類物件可以直接通過__class__屬性獲取自身型別:type
(3)繼承搜尋的順序發生了改變,經典類多繼承時屬性搜尋順序: 先深入繼承樹左側,再返回,開始找右側(即深度優先搜尋);新式類多繼承屬性搜尋順序: 先水平搜尋,然後再向上移動(即廣度優先搜尋)。
如下圖所示:
mro即method resolution order,主要用於在多繼承時判斷調的屬性的路徑(來自於哪個類)。
之前檢視了很多資料,說mro是基於深度優先搜尋演算法的。但不完全正確在Python2.3之前是基於此演算法,但從Python2.3起應用了新演算法:C3演算法。
為什麼採用C3演算法
C3演算法最早被提出是用於Lisp的,應用在Python中是為了解決原來基於深度優先搜尋演算法不滿足本地優先順序,和單調性的問題。
本地優先順序:指宣告時父類的順序,比如C(A,B),如果訪問C類物件屬性時,應該根據宣告順序,優先查詢A類,然後再查詢B類。
單調性:如果在C的解析順序中,A排在B的前面,那麼在C的所有子類裡,也必須滿足這個順序。
------------------------------新式類和舊式類中查詢屬性的順序不同-------------------------------------
在新式類中,查詢一個要呼叫的函式或者屬性的時候,是廣度優先搜搜的。
在舊式類當中,是深度優先搜尋的。