本文目錄一覽:
【面向對象】Python面向對象之多繼承算法
Python的類分為經典類和新式類:
官方推薦使用新式類替換經典類,因為經典類對於多重繼承採用的從左到右深度優先匹配算法存在一些問題。也就是如果方法同名,有的時候會繞過一些想要訪問的方法,只指向一個方法。
2.x版本中使用的是深度優先算法,而3.x版本使用的是c3算法,和廣度優先算法在某些情況下是不一樣的
以頂點為起始點,從左到右開始遍歷,當遍歷到一個節點的時候,判斷是否有左右兩個頂點,優先選擇左邊的作為頂點,再繼續遍歷下去,當遍歷完成後,選擇未曾訪問的頂點重新遍歷
如圖:根據深度優先算法,就是v1-v2-v4-v5-v3-v6
以頂點為起始點,從左到右開始遍歷,一層一層地向下遍歷,從左到右
如圖:根據廣度優先算法:就是v1-v2-v3-v4-v6-v5
C3 算法:MRO是一個有序列表L,在類被創建時就計算出來。
L(Child(Base1,Base2)) = [ Child + merge( L(Base1) , L(Base2) , Base1Base2 )]
L(object) = [ object ]
L的性質:結果為列表,列表中至少有一個元素即類自己。
“+” : 添加到列表的末尾,即 [ A + B ] = [ A,B ]
merge: ① 如果列表空則結束,非空 讀merge中第一個列表的表頭,
② 查看該表頭是否在 merge中所有列表的表尾中,或者不在表尾的第一個字母
②–③ 不在,則 放入 最終的L中,並從merge中的所有列表中刪除,然後 回到①中
②–④ 在,查看 當前列表是否是merge中的最後一個列表
④–⑤ 不是 ,跳過當前列表,讀merge中下一個列表的表頭,然後 回到 ②中
④–⑥ 是,異常。類定義失敗。
表頭: 列表的第一個元素 (列表:ABC,那麼表頭就是A,B和C就是表尾)
表尾: 列表中表頭以外的元素集合(可以為空)
merge 簡單的說即尋找合法表頭(也就是不在表尾中的表頭),如果所有表中都未找到合法表頭則異常。
例如:
L(D) = L(D(O))
= D + merge(L(O))
= D + O
= [D,O]
L(B) = L(B(D,E))
= B + merge(L(D) , L(E))
= B + merge(DO , EO) # 第一個列表DO的表頭D,其他列表比如EO的表尾都不含有D,所以可以將D提出來,即D是合法表頭
= B + D + merge(O , EO) #從第一個開始表頭是O,但是後面的列表EO的表尾中含有O所以O是不合法的,所以跳到下一個列表EO
= B + D + E + merge(O , O)
= [B,D,E,O]
同理:
L(C) = [C,E,F,O]
L(A(B,C)) = A + merge(L(B),L(C),BC)
= A + merge(BDEO,CEFO,BC)#B是合法表頭
= A + B + merge(DEO,CEFO,C)#D是合法表頭
= A + B + D + merge(EO,CEFO,C)#E不是合法表頭,跳到下一個列表CEFO,此時C是合法表頭
= A + B + D + C + merge(EO,EFO)#由於第三個列表中的C被刪除,為空,所以不存在第三個表,只剩下兩個表;此時E是合法表頭
= A + B + D + C + E + merge(O,FO)#O不是合法表頭,跳到下一個列表FO,F是合法表頭,
= A + B + D + C + E + F + merge(O,O)#O是合法表頭
= A + B + D + C + E + F + O
= [A,B,D,C,E,F,O]
L(D)
= L(D(B,C)) 取出D
= D + merge(BA+CA+BC) 查看merge的表頭,取出B,去除C,剩下A
= D + B + C + A
python多重繼承下super問題
樓上的回答的很正確,簡單來說:在對類D進行實例化的時候,你依次對類C和類A進行了初始化,結果就會以後初始化的B為準了
實際上在子類里並不需要去初始化父類,你在實例化子類的同時,繼承自父類的對象都會被創建
class A(object):
def __init__(self):
self.a = 1
class B(A):
def __init__(self):
self.a = 2
self.b = 2
class C(B,A):
pass
c = C()
c.a
2
另外補充一下。父類為新式類的情況下,繼承順序是有影響的。繼承順序上,經典類是深度優先,新式類是廣度優先,兩種混用的話,分分鐘就暈乎了。可以去多做做實驗,好好了解。
Python新式類和經典類的區別
A.在Python里凡是繼承了object的類,都是新式類
B.Python3里只有新式類
C.Python2裡面繼承object的是新式類,沒有寫父類的是經典類
D.經典類目前在Python里基本沒有應用
E.保持class與type的統一對新式類的實例執行a.class與type(a)的結果是一致的,對於舊式類來說就不一樣了
F.對於多重繼承的屬性搜索順序不一樣新式類是採用廣度優先搜索,舊式類採用深度優先搜索
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/158229.html