python之MRO和C3算法
2019-01-03 09:57:39来源:博客园 阅读 ()
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)
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
下一篇:大佬要我写自动邮件报表系统
- python3基础之“术语表(2)” 2019-08-13
- python3 之 字符串编码小结(Unicode、utf-8、gbk、gb2312等 2019-08-13
- Python3安装impala 2019-08-13
- 小白如何入门 Python 爬虫? 2019-08-13
- python_字符串方法 2019-08-13
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash