Python - 手推C3算法

C3算法規則

-- 每個類的繼承順序都是從基類向子類看
-- 造成一個指向關係的順序[當前類] + [父類的繼承順序]
-- 進行一個提取
-- 若是一個類出現從左到右的第一個順序上,而且沒有出如今後面的順序中,或者出如今後面順序了,可是仍然是第一個,那麼就把這個類提取出來

示例1

# class A(object): ...
# class B(A): ...
# class C(A): ...
# class D(B, C): ...
# print(D.__mro__)  # (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
'''手推mro,從上至下的順序
L(A) = [A] + [O]
A = [0]
A0 = []
L(A) = AO

L(B) = [B] + [A0]
B = [AO]
BA = [O]
BAO = []
L(B) = BAO

L(C) = [C] + [AO]
C = [AO]
CA = [0]
CAO = []
L(C) = CAO

L(D) = [D] + [BAO] + [CAO]
D = [BAO] + [CAO]
DB = [AO] + [CAO]
DBC = [AO] + [AO]
DBCA = [O] + [O]
DBCAO = []
L(D) = DBCA0
'''

示例2

# class G(object): ...
# class E(G): ...
# class D(object): ...
# class F(object): ...
# class B(D, E): ...
# class C(D, F): ...
# class A(B, C): ...
# print(A.__mro__)  #  ABCDEGFO  (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.E'>, <class '__main__.G'>, <class '__main__.F'>, <class 'object'>)
'''手推C3算法
L(G) = [G] + [O]
G = [O]
GO = []
L(G) = GO

L(E) = [E] + [G0]
E = [GO]
EG = [O]
EGO = []
L(E) = EGO

L(D) = [D] + [DO]
D = [O]
DO = []
L(D) = DO

L(F) = [F] + [FO]
F = [O]
FO = []
L(F) = FO

L(B) = [B] + [DO] + [EGO]
B = [DO] + [EGO]
BD = [O] + [EGO]
BDE = [O] + [GO]
BDEG = [O] + [O]
BDEGO = []
L(B) = BDEGO

L(C) = [C] + [DO] + [FO]
C = [DO] + [FO]
CD = [O] + [FO]
CDF = [O] + [O]
CDFO = []
L(C) = CDFO

L(A) = [A] + [BDEGO] + [CDFO]
A = [BDEGO] + [CDFO]
AB = [DEGO] + [CDFO]
ABC = [DEGO] + [DFO]
ABCD = [EGO] + [FO]
ABCDE = [GO] + [FO]
ABCDEG = [O] + [FO]
ABCDEGF = [O] + [O]
ABCDEGFO = []
L(A) = ABCDEGFO
'''

應用

看代碼,請說出執行流程python

 1 class A(object):
 2     def __init__(self):
 3         print("enter A")
 4         print("leave A")
 5 class B(object):
 6     def __init__(self):
 7         print("enter B")
 8         print("leave B")
 9 class C(A):
10     def __init__(self):
11         print("enter C")
12         super().__init__()
13         print("leave C")
14 class D(A):
15     def __init__(self):
16         print("enter D")
17         super().__init__()
18         print("leave D")
19 class E(B, C):
20     def __init__(self):
21         print("enter E")
22         B.__init__(self)
23         C.__init__(self)
24         print("leave E")
25 class F(E, D):
26     def __init__(self):
27         print("enter F")
28         E.__init__(self)
29         D.__init__(self)
30         print("leave F")
31 F()
32 # print(F.__mro__)  # FEBCDA0 (<class '__main__.F'>, <class '__main__.E'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.A'>, <class 'object'>)
33 # 打印結果以下示例
34 '''
35 enter F
36 enter E
37 enter B
38 leave B
39 enter C
40 enter D
41 enter A
42 leave A
43 leave D
44 leave C
45 leave E
46 enter D
47 enter A
48 leave A
49 leave D
50 leave F
51 '''
demo

解:

首先觀察代碼,畫出繼承順序圖算法

那麼這裏爲何要用到c3算法,就是爲了算出mro順序(這裏只能手推,不能打印)。當算出來mro順序以後,咱們就能夠在後面用到了。ide

'''

L(A) = [A] + [O]
A = [0]
AO = []
L(A) = AO

L(B) = [B] + [O]
B = [O]
BO = []
L(B) = BO

L(C) = [C] + [AO]
C = [AO]
CA = [O]
CAO = []
L(C) = CAO

L(D) = [D] + [AO]
D = [AO]
DA = [O]
DAO = []
L(D) = DAO

L(E) = [E] + [BO] + [CAO]
E = [BO] + [CAO]
EB = [O] + [CAO]
EBC = [O] + [AO]
EBCA = [O] + [O]
EBCAO = []
L(E) = EBCAO

L(F) = [F] + [EBCAO] + [DAO]
F = [EBCAO] + [DAO]
FE = [BCAO] + [DAO]
FEB = [CAO] + [DAO]
FEBC = [AO] + [DAO]
FEBCD = [AO] + [AO]
FEBCDA = [O] + [O]
FEBCDAO = []
L(F) = FEBCDAO
'''
手推C3算法,求出mro順序

一番推算,mro的順序爲FEBCDAO。spa

接下來,咱們開始解釋代碼的執行流程。3d

'''
先把mro的繼承順序,放這裏:FEBCDAO
1. 代碼從第F()開始執行,執行其內部的init方法首先打印enter F
2. 執行E中的init方法,打印一行enter E
3. 執行B中的init方法,打印enter B,緊接着打印leave B,執行完畢,代碼回到E中
4. 執行C中的init方法,打印enter C, 而後調用父類的super方法,
    那該執行父類的init方法,這裏要知道C的父類是誰?是A嗎?(注意,關鍵點來了)
    不是!而是順着mro的順序查找,C後面是D,因此,執行D的init方法
    首先打印enter D, 接着D又執行super方法,找父類的super方法,mro中是A
    因此執行A中的init方法,打印enter A,在打印leave A,而後,回到D中
    又打印leave D,執行完畢,回到C中
    打印leave C,執行完畢,回到E中
    打印leave E,E此時也執行完畢,回到最開始的F中
5. 執行D中init方法
    首先打印enter D
    調用父類的super方法,從mro找父類
        打印enter A
        打印leave A
        A執行完畢,回到D中
    打印leave D
    執行完畢,回到最初F中
6. 打印leave F,程序結束
    
enter F
enter E
enter B
leave B
enter C
enter D
enter A
leave A
leave D
leave C
leave E
enter D
enter A
leave A
leave D
leave F
'''

 


that's allcode

相關文章
相關標籤/搜索