• python之MRO和C3算法


    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)
    复制代码
  • 相关阅读:
    在ubuntu下复制文件出现权限不够的解决方法
    Ubuntu安装ROS Melodic
    gedit文件操作
    Linux下强制删除文件和权限操作
    VMware Tools 继续运行脚本未能在虚拟机中成功运行 解决方式
    Linux解压命令
    Ubuntu 18.04.4 LTS(Bionic Beaver)安装
    Socket层实现系列 — send()类发送函数的实现
    iOS7 CookBook精彩瞬间(三)UIActivityViewController的基本使用及自定义Activity
    iOS7 CookBook精彩瞬间(二)NSSet、通过Subscript访问类成员等
  • 原文地址:https://www.cnblogs.com/q455674496/p/10208655.html
Copyright © 2020-2023  润新知