天天看點

python mro c3_Python3中的C3算法:多繼承查找規則

Python3中的C3算法:多繼承查找規則

Python3探索

一、基本概念

1. mro序列

MRO是一個有序清單L,在類被建立時就計算出來。如果繼承至一個基類:class B(A)

這時B的mro序列為

mro( B ) = mro( B(A) )

= [B,A]

如果繼承至多個基類:class B(A1,A2,A3 ...)

這時B的mro序列

mro(B) = mro( B(A1,A2,A3 …) )

= [B] + merge(mro(A1), mro(A2), mro(A3) ..., [A1,A2,A3])

計算結果為清單,清單中至少有一個元素即類自己,如上述示例[A1,A2,A3]。merge操作是C3算法的核心。

2. 表頭和表尾:表尾:

清單中表頭以外的元素集合(可以為空)

表頭:

清單的第一個元素

示例

清單:[A, B, C]

表頭是A,表尾是B和C

3. merge操作:

merge操作流程圖:

Created with Raphaël 2.1.2Start① 判斷merge清單是否為空?>>是空。如果清單為空,本次merge操作結束,如有下次計算則繼續>>不是空。如果清單非空,讀取merge中第一個清單的表頭繼續判斷下一步② 檢視該表頭是否在merge中的所有清單的表尾中?>>不在,則将該表頭放入最終的L中(外層)并從merge中的所有清單中删除,然後回到①中>>在,繼續判斷下一步③ 檢視目前清單是否是merge中的最後一個清單?>>不是,跳過目前清單,回到①中查找下一個清單>>是,異常。類定義失敗。End回到①yesnoyesnoyesno

二、執行個體

1. 計算執行個體1

示例:(多繼承UML圖,引用見參考)

python mro c3_Python3中的C3算法:多繼承查找規則

備注:O==object

如何計算mro(A) ?mro(A) = mro( A(B,C) )

原式= [A] + merge( mro(B),mro(C),[B,C] )

mro(B) = mro( B(D,E) )

= [B] + merge( mro(D), mro(E), [D,E] )

= [B] + merge( [D,O] , [E,O] , [D,E] )

= [B,D] + merge( [O] , [E,O] , [E] )

= [B,D,E] + merge([O] , [O])

= [B,D,E,O]

mro(C) = mro( C(E,F) )

= [C] + merge( mro(E), mro(F), [E,F] )

= [C] + merge( [E,O] , [F,O] , [E,F] )

= [C,E] + merge( [O] , [F,O] , [F] )

= [C,E,F] + merge([O] , [O])

= [C,E,F,O]

原式= [A] + merge( [B,D,E,O], [C,E,F,O], [B,C])

= [A,B] + merge( [D,E,O], [C,E,F,O], [C])

= [A,B,D] + merge( [E,O], [C,E,F,O], [C]) # 此步為重點,跳過E

= [A,B,D,C] + merge([E,O], [E,F,O])

= [A,B,D,C,E] + merge([O], [F,O]) # 跳過O

= [A,B,D,C,E,F] + merge([O], [O])

= [A,B,D,C,E,F,O]

2. 代碼測試

對于以上計算,用代碼來測試。

classD:pass

classE:pass

classF:pass

classB(D,E):pass

classC(E,F):pass

classA(B,C):pass

print("從A開始查找:")

forsinA.__mro__:

print(s)

print("從B開始查找:")

forsinB.__mro__:

print(s)

print("從C開始查找:")

forsinC.__mro__:

print(s)

結果:從A開始查找:

從B開始查找:

從C開始查找:

三、總結

每次判斷如何讀取都要這麼麻煩計算嗎?可有簡單方法?

我對此做了一個簡單總結。

1. 規律總結

如何快速判斷查找規律?從 “目前子類” 向上查找它的父類,

若 “目前子類” 不是 “查找的父類” 的最後一個繼承的子類時,則跳過該 “查找的父類” 的查找,開始查找 “目前子類” 的下一個父類

查找規律流程圖:

Created with Raphaël 2.1.2Start① 從 “目前子類” 向上查找它的父類② 判斷該父類屬性。目前父類是否還有後續其他子類?若是。則跳過目前父類。對目前子類, 開始查找下一個父類若沒有後續子類。則将該父類記錄進入__mro__清單———End一次查找結束yesno

2. 規律測試

執行個體2:

對于如下繼承:

python mro c3_Python3中的C3算法:多繼承查找規則

通過如下判斷模式:

代碼測試:

classA1:pass

classA2:pass

classA3:pass

classB1(A1,A2):pass

classB2(A2):pass

classB3(A2,A3):pass

classC1(B1):pass

classC2(B1,B2):pass

classC3(B2,B3):pass

classD(C1,C2,C3):pass

print("從D開始查找:")

forsinD.__mro__:

print(s)

print("從C3開始查找:")

forsinC3.__mro__:

print(s)

結果預測:

四、參考