mro即 method resolution order (方法解釋順序),主要用於在多繼承時判斷屬性的路徑(來自於哪個類)。
在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操作的序列無法為空,則說明不合法。
例子:實現c3演算法的**
#-*- encoding:gbk -*-#
def mro_c3(*cls):
if len(cls)==1:
ifnot cls[0].__bases__
:
return
cls
else
:
return cls+ mro_c3(*cls[0].__bases__
)
else
: seqs = [list(mro_c3(c)) for c in cls ] +[list(cls)]
res =
while
true:
non_empty =list(filter(none, seqs))
ifnot
non_empty:
return
tuple(res)
for seq in
non_empty:
candidate =seq[0]
not_head = [s for s in non_empty if candidate in s[1:]]
ifnot_head:
candidate =none
else
:
break
ifnot
candidate:
raise typeerror("
inconsistent hierarchy, no c3 mro is possible
")
for seq in
non_empty:
if seq[0] ==candidate:
del seq[0]
內容摘自:
Python多繼承C3演算法
python3 多繼承的mro演算法選擇。mro method resolution order 方法解析順序。python3 只保留了c3演算法!c3演算法解析 1.c3演算法解析 c3演算法 mro是乙個有序列表l,在類被建立時就計算出來了。l child base1,base2 child m...
多繼承c3演算法
一.mro mro即 method resolution order 方法解釋順序 主要用於在多繼承時判斷屬性的路徑 來自於哪個類 print 類.mro 得到屬性路徑按繼承順序 在python2.2版本中,演算法基本思想是根據每個祖先類的繼承結構,編譯出一張列表,包括搜尋到的類,按策略刪除重複的。...
python多重繼承C3演算法
python多重繼承的mro演算法選擇 經典方式 python2.2 新式演算法 python2.3 新式演算法 c3 python 3中只保留了最後一種,即c3演算法 c3演算法的解析 1.多繼承uml圖 備註 o object 2.python c3演算法解析 c3 定義引用開始 c3 演算法 ...