在 python 2.2 以後,python 實現了一個新的MRO算法:C3算法,用於方法解析順序 。 python
1、什麼是方法解析順序 算法
方法解析順序 :多重繼承時,用於在子類中調用父類方法時肯定調用哪一個父類的方法 。 編程
多重繼承代碼示例:
#!/usr/bin/python #-*- coding:utf8 -*- class A(object): def echo(self): print "class_A" class B(A): pass #def echo(self): # print "class_B" class C(A): def echo(self): print "class_C" class D(B,C): pass print D.__mro__ //python使用__mro__ 來存儲線性化計算的結果。
ubuntu@yee:/tmp$ python mro.py (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)能夠看到順序爲: D --> B --> C --> A --> object
當子類D調用echo方法時: ubuntu
D().echo()python 先搜索 D 本地類,再搜索B,有則返回,無則繼續搜索C ,以此類推。
2、C3算法的原理 spa
上面示例代碼中所用到的正是C3算法,算法的表達式爲: code
L[D(B,C)]
= D + merge(L[B],L[C],[B,C])
以上表達式也等同於:
==>
L[D(B,C)] = D + merge(mro(B,object),mro(C,object),[B,C]) ==> L[D(B,C)] = D + merge( [B,object], [C, object],[B,C]) [] : 列表表達式
merge: C3算法的核心
《python高級編程》中是這樣寫的:
取第一個列表的頭,也就是L[B,object] ,若是這個頭不在任何表的尾部,那麼將它加到Class D的線性化中,而且從合併中的列表裏刪除 ;不然查找下一個列表的頭,若是是個好的表頭則取出它。 須要注意的是: 表頭指是第一個元素 ,尾部是指除表頭以外的其它全部元素 。如[A,B,C,D,E,F],A是表頭,[B,C,D,E,F]是尾部。
方式解析: 繼承
L(D(B,C)) = D + merge( [B,object] ,[C,object] , [B,C] ) class
#列表[B,object]的表頭是B,沒有出如今其它表([C,object] 、[B,C] )的尾部 原理
= [D, B] + merge( [object], [C,object] , [C] ) object
#列表[C,object]的表頭是C,沒有出如今其它表([object] 、[C] )的尾部 ,注意 [C] 這個列表只有表頭,沒有尾部
= [D, B,C] + merge( [object] , [object] )
= [D, B,C,object]
經過以上的運算,能夠得出跟 D().__mro__ 同樣的結果 。