一.mro
mro即 method resolution order (方法解釋順序),主要用於在多繼承時判斷屬性的路徑(來自於哪個類)。
print(類.mro)得到屬性路徑按繼承順序
在python2.2版本中,演算法基本思想是根據每個祖先類的繼承結構,編譯出一張列表,包括搜尋到的類,按策略刪除重複的。但是,在維護單調性方面失敗過(順序儲存),所以從2.3版本,採用了新演算法c3。
二.為什麼採用c3演算法
c3演算法最早被提出是用於lisp的,應用在python中是為了解決原來基於深度優先搜尋演算法不滿足本地優先順序,和單調性的問題。
本地優先順序:指宣告時父類的順序,比如c(a,b),如果訪問c類物件屬性時,應該根據宣告順序,優先查詢a類,然後再查詢b類。
單調性:如果在c的解析順序中,a排在b的前面,那麼在c的所有子類裡,也必須滿足這個順序。
三.c3演算法
判斷mro要先確定乙個線性序列,然後查詢路徑由由序列中類的順序決定。所以c3演算法就是生成乙個線性序列。
如果繼承至乙個基類:
class b(a)
這時b的mro序列為[b,a]
如果繼承至多個基類
class b(a1,a2,a3 ...)
這時b的mro序列 mro(b) = [b] + merge(mro(a1), mro(a2), mro(a3) ..., [a1,a2,a3])
merge操作就是c3演算法的核心。
遍歷執行merge操作的序列,如果乙個序列的第乙個元素,是其他序列中的第乙個元素,或不在其他序列出現,則從所有執行merge操作序列中刪除這個元素,合併到當前的mro中。
merge操作後的序列,繼續執行merge操作,直到merge操作的序列為空。
如果merge操作的序列無法為空,則說明不合法。
class a(object):pass例子class b(object):pass
class c(object):pass
class e(a,b):pass
class f(b,c):pass
class g(e,f):pass
#a、b、c都繼承至乙個基類,所以mro序列依次為[a,o]、[b,o]、[c,o]
#mro(e) = [e] + merge(mro(a), mro(b), [a,b])
#= [e] + merge([a,o], [b,o], [a,b])
#執行merge操作的序列為[a,o]、[b,o]、[a,b]
#a是序列[a,o]中的第乙個元素,在序列[b,o]中不出現,在序列[a,b]中也是第乙個元素,所以從執行merge操作的序列([a,o]、[b,o]、[a,b])中刪除a,合併到當前mro,[e]中。
#mro(e) = [e,a] + merge([o], [b,o], [b])##
mro(e) = [e,a,b] + merge([o], [o])
#= [e,a,b,o]
print(e.__mro__) #
(, , , )
Python多繼承C3演算法
python3 多繼承的mro演算法選擇。mro method resolution order 方法解析順序。python3 只保留了c3演算法!c3演算法解析 1.c3演算法解析 c3演算法 mro是乙個有序列表l,在類被建立時就計算出來了。l child base1,base2 child m...
python多繼承之C3演算法
mro即 method resolution order 方法解釋順序 主要用於在多繼承時判斷屬性的路徑 來自於哪個類 在python2.2版本中,演算法基本思想是根據每個祖先類的繼承結構,編譯出一張列表,包括搜尋到的類,按策略刪除重複的。但是,在維護單調性方面失敗過 順序儲存 所以從2.3版本,採...
python多重繼承C3演算法
python多重繼承的mro演算法選擇 經典方式 python2.2 新式演算法 python2.3 新式演算法 c3 python 3中只保留了最後一種,即c3演算法 c3演算法的解析 1.多繼承uml圖 備註 o object 2.python c3演算法解析 c3 定義引用開始 c3 演算法 ...