參考:
類c的線性化記憶為l[c]=[c1,c2,...cn],其中c1稱為l[c]的頭,其餘元素[c2,...cn]稱為尾。如果乙個類c繼承自基類b1,b2,...,b那麼l[c]的計算過程為
#類object為最高父類,所有類都繼承objectmerge是將一組列表輸出為乙個列表,其過程為l[objicet]=[object]
l[c(b1,b2,...bn)]=[c]+merge(l[b1],l[b2],[b1,b2,...bn])
1,檢查第乙個列表的頭元素,記做h舉例說明2,如果h是後續序列的第乙個元素,或者不在後續序列中再次出現,則將其輸出,並將其從所有列表中刪除,如果不符合跳過此元素,查詢下乙個列表的第乙個元素,然後回到步驟1
3,重複上述步驟,直至列表為空或者不能再找出可以輸出的元素。
>>> class a(object):首先object,a,b的線性化結果比較簡單... pass
...
>>> class b(object):
... pass
...
>>> class c(a,b):
... pass
l[object]=[object]python內建變數__mro__儲存了l[a]=[a,object]
l[b]=[b,object]
>>> object.__mro__需要計算出l[c](,)>>> a.__mro__
(, )
>>> b.__mro__
(, )
l[c]=[c]+merge(l[a],l[b],[a,b])使用__mro__驗證計算結果正確=[c]+mergr([a,object],[b,object],[a,b])
#取得的第乙個元素是a,是序列[a,b]的第乙個元素所以輸出a並且將a從所有列表中刪除
=[c,a]+merge([object],[b,object],[b])
#取得的元素為object不滿足條件,object是序列[b,object]的最後乙個元素,跳過取到元素為b,滿足條件,將b輸出並從所有列表刪除b
=[c,a,b]+merge([object],[object])
#最後的結果
=[c,a,b,object]
>>> c.__mro__乙個複雜的例子(, , , )
class b(object): pass計算過程class c(object): pass
class d(a,c): pass
class e(b,c): pass
class f(d,e): pass
l[f] = [f] + merge(l[d], l[e], [d, e])驗證計算結果= [f] + merge([d, a, c, object], [e, b, c, object], [d, e])
= [f, d] + merge([a, c, object], [e, b, c, object], [e])
= [f, d, a] + merge([c, object], [e, b, c, object], [e])
= [f, d, a, e] + merge([c, object], [b, c, object])
= [f, d, a, e, b] + merge([c, object], [c, object])
= [f, d, a, e, b, c, object]
(, , , , , , )以上演算法雖然可以計算出繼承順序,但是不直觀 ,可以使用圖示拓撲順序進行推導
什麼是拓撲順序
在圖論中,拓撲順序(topological storting)是乙個有向無環圖(dag,directed acyclic graph)的所有定點的線性序列。且該序列必須滿足一下兩個條件
1,每個頂點出現且只出現一次
2,若存在一條從頂點a到頂點b的路徑,那麼在序列中頂點a出現在頂點b的前面
看下圖
它是乙個dag圖,那麼如果寫出它的拓撲順序呢?一種比較常見的方法
1,從dag途中選擇乙個沒有前驅(即入度為0)的頂點並輸出
2,從圖中刪除該頂點和所有以它為起點的有向邊
3,重複1和2直到當前dag圖為空或者當前途中不存在無前驅的頂點為止。
於是得到拓撲排序後的結果為
看例項
class a(object):根據上述繼承關係構成一張圖pass
class b(object):
pass
class c1(a,b):
pass
class c2(a,b):
pass
class d(c1,c2):
pass
1,找到入度為0的點,只有乙個d,把d拿出來,把d相關的邊減掉
2,現在有兩個入度為0的點(c1,c2),取最左原則,拿c1,減掉c1相關的邊,這時候的排序是
3, 現在入度為0的點(c2),拿掉c2,減掉c2相關的邊,這時候的排序是
4,現在入度為0的點(a,b),取最左原則,拿掉a,減掉a相關的邊,這時候的排序是
5,現在入度為0的點只有b,拿掉b,減掉b相關的邊,最後只剩下object
所以最後的排序是
驗證一下結果
>>> d.__mro__為了進一步屬性,在看乙個例子(, , , , , )
class a(object):繼承圖pass
class b(object):
pass
class c1(a):
pass
class c2(b):
pass
class d(c1,c2):
pass
1,找到入度為0的頂點,只有乙個d,拿d,剪掉d相關的邊
2,得到兩個入度為0的頂點(c1,c2),根據最左原則,拿c1,剪掉c1相關的邊,這時候序列為
3,接著看,入度為0的頂點有兩個(a,c1),根據最左原則,拿a,剪掉a相關的邊,這時候序列為
4,接著看,入度為0的頂點為c2,拿c2,剪掉c2相關的邊,這時候序列為
5,繼續,入度為0的頂點為b,拿b,剪掉b相關的邊,最後還有乙個object
所以最後的序列為
(, , , , , )使用圖示拓撲法可以快速計算出繼承順序
python3中多重繼承的問題
本來以為多重繼承很簡單,但是多看了一些資料後發現還是挺複雜的。如果繼承情況簡單就還比較好理解,但是如果繼承的情況太過於複雜的話,python3 中會使用拓撲排序的方式來尋找繼承的父類。有關繼承的拓撲排序 關於這方面看上面的文章就可以了。我下面給出除此之外的一些說明 class a object de...
python 多重繼承之拓撲排序
在圖論中,拓撲排序 topological sorting 是乙個有向無環圖 dag,directed acyclic graph 的所有頂點的線性序列。且該序列必須滿足下面兩個條件 例如,下面這個圖 它是乙個dag圖,那麼如何寫出它的拓撲順序呢?這裡說一種比較常用的方法 於是,得到拓撲排序後的結果...
python 多重繼承之拓撲排序
在圖論中,拓撲排序 topological sorting 是乙個有向無環圖 dag,directed acyclic graph 的所有頂點的線性序列。且該序列必須滿足下面兩個條件 例如,下面這個圖 它是乙個dag圖,那麼如何寫出它的拓撲順序呢?這裡說一種比較常用的方法 於是,得到拓撲排序後的結果...