Python的MRO以及C3線性化演算法

2022-08-23 23:00:15 字數 1653 閱讀 3695

python3 中的方法解析順序 (method resolution order , mro)採用c3線性化演算法來確定

簡而言之,乙個類的mro應當如下確定

l[object] = [object]

l[c(b1…bn)] = [c] + merge(l[b1]…l[bn], [b1, … ,bn])

這裡的關鍵在於 merge,其輸入是一組列表,按照如下方式輸出乙個列表:

檢查第乙個列表的頭元素(如 l[b1] 的頭),記作 h。

若 h 未出現在其它列表的尾部,則將其輸出,並將其從所有列表中刪除,然後回到步驟1;否則,取出下乙個列表的頭部記作 h,繼續該步驟。

重複上述步驟,直至列表為空或者不能再找出可以輸出的元素。如果是前一種情況,則演算法結束;如果是後一種情況,說明無法構建繼承關係,python 會丟擲異常。

示例1繼承關係如下圖

根據上述c3演算法的步驟來計算其mro

首先計算b1的mro:

l[b1(a1,a2)] = [b1] + merge(l[a1], l(a2), [a1, a2])

= [b1] + merge([a1,obj], [a2,obj], [a1,a2])

= [b1, a1] + merge([obj], [a2,obj], [a2])

= [b1, a1, a2] + merge([obj], [obj])

= [b1, a1, a2, obj]

同理,計算b2的mro(過程略):

l[b2(a3)] = [b2, a3, obj]

最終計算並得到c的mro

l[c(b1,b2)] = [c] + merge(l[b1(a1,a2)], l[b2(a3)], [b1,b2])

= [c] + merge([b1, a1, a2, obj], [b2, a3, obj], [b1,b2])

= [c, b1] + merge([a1, a2, obj], [b2, a3, obj], [b2])

= [c, b1, a1] + merge([a2, obj], [b2, a3, obj], [b2])

= [c, b1, a1, a2] + merge([obj], [b2, a3, obj], [b2])

= [c, b1, a1, a2, b2] +merge([obj], [a3, obj])

= [c, b1, a1, a2, b2, a3] +merge([obj], [obj])

= [c, b1, a1, a2, b2, a3, obj]

根據c3演算法成功構建了mro,所以這個類的繼承關係是被允許的,而且根據mro可以明確地指出應當如何去查詢其父類的屬性/方法。即按照mro列表由前向後的順序來查詢。

當然,我們完全沒有必要去計算這個序列,直接使用.mro()類方法即可檢視該類的mro

c.mro()
[, , , , , , ]
與我們計算的結果是相同的。

正確理解mro是使用多重繼承和super()完成多繼承類協作任務的基礎。

參考鏈結

python的方法解析順序(mro)***

mro之C3演算法

c3演算法 歸併演算法 class a object pass class b a pass class c a pass class d b pass class e c pass class f d,e pass print f.mro 第一步先找到繼承的父類的mro d d,b,a,o e e...

mro和c3 演算法

mro案例 class a pass class b a pass class c a pass class d b,c pass class e c,a pass class f d,e pass class g e pass class h g,f pass 計算方法 先將每乙個類的繼承mro,...

Python之MRO及其C3演算法

你真的理解python中mro演算法嗎?python mro c3演算法 mro method resolution order方法解析順序,python支援多繼承,該方法用於解決父類存在同名函式的時存在的二義性問題。單調性 某乙個類繼承的父類滿足從左到右的順序解析 從左到右遞迴地從左到右解析 獲取...