python之MRO和C3算法

六月ゝ 毕业季﹏ 提交于 2020-05-08 02:18:04

python2类和python3类的区别
pyhon2中才分新式类与经典类,python3中统一都是新式类
Python 2.x中默认都是经典类,只有显式继承了object才是新式类
python 3.x中默认都是新式类,经典类被移除,不必显式的继承object
改变了经典类中一个多继承的bug,因为其采用了广度优先的算法

复制代码
复制代码
1 class A(object):
 2     def test(self):
 3         print('from A')
 4 
 5 class B(A):
 6     def test(self):
 7         print('from B')
 8 
 9 class C(A):
10     def test(self):
11         print('from C')
12 
13 class D(B):
14     def test(self):
15         print('from D')
16 
17 class E(C):
18     def test(self):
19         print('from E')
20 
21 class F(D,E):
22     # def test(self):
23     #     print('from F')
24     pass
25 f1=F()
26 f1.test()
27 print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性
28 #新式类继承顺序:F->D->B->E->C->A
29 #经典类继承顺序:F->D->B->A->E->C
复制代码
复制代码

MRO: method resolution order 方法的查找顺序
经典类的MRO 树形结构的深度优先遍历 --> 树形结构遍历

 

复制代码
复制代码
1 class A:
 2     pass
 3 class B(A):
 4     pass
 5 class C(A):
 6     pass
 7 class D(B, C):
 8     pass
 9 class E:
10     pass
11 class F(D, E):
12     pass
13 class G(F, D):
14     pass
15 class I:
16     pass
17 class J(B, C):
18     pass
19 class K(A):
20     pass
21 class H(I, J, K):
22     pass
23 class Foo(H, G):
24     pass
25 print(Foo.__mro__)
26 结果
27 Foo -->H-->I-->J-->G-->F-->D-->B-->C-->K-->A-->E-->'object'
复制代码
复制代码

新式类的MRO C3算法
1. 拆分
2. 合并

复制代码
复制代码
1 class A:
 2     pass
 3 class B(A):
 4     pass
 5 class C(A):
 6     pass
 7 class D(B, C):
 8     pass
 9 class E(C, A):
10     pass
11 class F(D, E):
12     pass
13 class M:
14     pass
15 class N(M):
16     pass
17 class P(E, A):
18     pass
19 class X:
20     pass
21 class Q(P,N,X):
22     pass
23 class G(Q, F):
24     pass
25 class H(G, F):
26     pass
27 
28 
29 加法:merge(),拿第一项的第一位和后面项除了第一位的每位比较,如果没有出现,则该位元素算出
30 如果出现了,此时开始下一项的第一位继续和后面项除了第一位的每一位比较,
31 如果后边项里除了第一位的其他位出现有,则继续开始拿下一项的第一位和后一项除了第一位的其他位做比较
32 如果后边项没有出现,取完这一项的第一位后,重新返回第一项继续执行判断第一项的第一位与后边项除了第一位比较
33 
34 比如
35 F + DBCA + ECA + DE
36 DBCA + ECA + DE
37 BCA + ECA + E
38 CA + CA
39 A + A
40 
41 思路:
42 第一次拿第一项的第一位F与DBCA,ECA,DE比较,这三个数除了第一位后面的每一项都没有F出现,
43 所以把所有的F消除,取值F
44 第二次拿第二项DBCA的第一位D与ECA,DE比较,这两数中除了第一位后边的每一项都没有D出现,
45 所以就把所有的D消除,然后取值D
46 第三次拿第二项BCA的B与ECA,E比较,这两个数中除了第一位后边的每一项都没有B出现,
47 所以就把所有的B消除,取值B
48 第四次拿第二项CA的C与ECA,E比较,ECA出现了C,所以不动CA,然后拿下一项的ECA的第一位E与最后一项的值E做比较,
49 因为ECA的E重复了最后一项E,所以也不动ECA,然后拿最后一项的E与后边作比较,因为后边没项值,
50 所以消除所有的E,取值E
51 第四次拿返回开头拿第二项CA中的C与后边的项CA做比较,因为后边项中除了第一位,其他位没有C,
52 所以消除所有的C,取值C
53 第五次拿第二项的A与后边的项A做比较,因为后边项值有A,所有拿后边项A与后边项做比较,因为后边项没有值,
54 所以消除所有的A,取值A
55 结果
56 FDBECA
57 
58 
59 求H的MRO
60 设求MRO的算法是L
61 解析步骤:
62                                     拆分                          合并      
63 L(H) = H + L(G) + L(F) + GF #H + GQPFDBECANMX + FDBECA + GF = HGQPFDBECANMX
64 L(G) = G + L(Q) + L(F) + QF #G + QPECANMX + FDBECA + QF = GQPFDBECANMX
65 L(Q) = Q + L(P) + L(N) + L(X) + PNX #Q + PECA + NM + X + PNX = QPECANMX
66 L(X) = X    #X
67 L(P) = P + L(E) + L(A) + EA #P + ECA + A + EA = PECA
68 L(N) = N + L(M) + M     #N + M + M = NM
69 L(M) = M    #M
70 L(F) = F + L(D) + L(E) + DE #F + DBCA + ECA + DE = FDBECA
71 L(E) = E + L(C) + L(A) + CA #E + CA + A + CA = ECA
72 L(D) = D + L(B) + L(C) + BC #D + BA + CA + BC = DBCA
73 L(C) = C + L(A) + A     #C + A + A = CA
74 L(B) = B + L(A) + A     #B + A + A = BA
75 L(A) = A    #A
76 所以结果是
77 HGQPFDBECANMX
78 
79 和电脑运算的结果一致
80 print(H.__mro__)
复制代码
复制代码

super() 找MRO顺序的下一个

复制代码
复制代码
1 class Base1:
 2     def chi(self):
 3         print("我是Base1")
 4 
 5 class Base2:
 6     def chi(self):
 7         print("我是Base2")
 8 
 9 class Base3:
10     def chi(self):
11         print("我是Base3")
12 
13 class Bar(Base1, Base2, Base3):
14     def chi(self):
15         print("我是Bar里面的chi1")
16         # super(类名, self)  从某个类开始找下一个MRO
17         super(Base2, self).chi()    # 此时调用的super. 在Bar调用 -> super表示找MRO里的下一个
18         # super().chi() # super(Bar, self).chi()
19         print("我是Bar里面的chi2")
20 
21 b = Bar()   # Bar, Base1, Base2, Base3, object
22 b.chi()
23 print(Bar.__mro__)
24 
25 结果:
26 我是Bar里面的chi1
27 我是Base3
28 我是Bar里面的chi2
29 (<class '__main__.Bar'>, <class '__main__.Base1'>, <class '__main__.Base2'>, <class '__main__.Base3'>, <class 'object'>)
30 
31 
32 事例2
33 class Base1:
34     def chi(self):
35         super().chi()
36         print("我是Base1")
37 
38 class Base2:
39     def chi(self):
40         super().chi()
41         print("我是Base2")
42 
43 class Base3:
44     def chi(self):
45         print("我是Base3")
46 
47 class Bar(Base1, Base2, Base3):
48     def chi(self):
49         print("我是Bar里面的吃1")
50         super(Bar, self).chi()
51         print("我是Bar里面的吃2")
52 
53 b = Bar()
54 b.chi()
55 
56 结果
57 我是Bar里面的吃1
58 我是Base3
59 我是Base2
60 我是Base1
61 我是Bar里面的吃2
复制代码
复制代码

MRO + super 面试题

复制代码
复制代码
1 class Init(object):
 2     def __init__(self, v):
 3         print("init")
 4         self.val = v
 5 
 6 class Add2(Init):
 7     def __init__(self, val):
 8         print("Add2")
 9         super(Add2, self).__init__(val)
10         print(self.val)
11         self.val += 2
12 
13 class Mult(Init):
14     def __init__(self, val):
15         print("Mult")
16         super(Mult, self).__init__(val)
17         self.val *= 5
18 
19 class HaHa(Init):
20     def __init__(self, val):
21         print("哈哈")
22         super(HaHa, self).__init__(val)
23         self.val /= 5
24 
25 class Pro(Add2,Mult,HaHa):
26     pass
27 
28 class Incr(Pro):    # incr->pro->add2->Mult->HaHa->init
29     def __init__(self, val):
30         super(Incr, self).__init__(val)
31         self.val += 1
32 p = Incr(5)
33 print(p.val)
复制代码
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!