6.MRO和C3算法

Posted xiaoqianbook

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了6.MRO和C3算法相关的知识,希望对你有一定的参考价值。

经典类的MRO

python3以不存在经典类

class A:
    pass
class B(A):
    pass
class C(A):
    pass
class D(B, C):
    pass
class E:
    pass
class F(D, E):
    pass
class G(F, D):
    pass
class H:
    pass
class Foo(H, G):
    pass

分析

技术分享图片

类的MRO顺序是 foo->H->G->F->D->B->A->C->E,从左往右的顺序

新式类的MRO

 python中的新式类的MRO是采用的C3算法来完成的

class A:
    pass
class B(A):
    pass
class C(A):
    pass
class D(B, C):
    pass
class E(C,A):
    pass
class F(D, E):
    pass
class G(E):
    pass
class H(G,F):
    pass
print(H.__mro__)

3C算法

L(H) = H + L(G) + L(F) + GF

L(G) = G + L(E) + E

L(F) = F + L(D) + L(E) + DE

L(D) = D + L(B) + L(C) + BC

L(B) = B + L(A) + A

L(A) = A

L(E) = E + L(C) + L(A) + CA

L(C) = C + L(A) + A

加法:merge(), 拿第一项的第一位和后面每项的除了第一位比较. 如果没有出现, 则该位元素算出
如果出现了. 此时开始下一项的第一位继续和后面每一项的除了第一位比较:
用头和后面身体比较

转换

L(C) = C + A + A #CA

L(E) = E + CA + A #ECA

L(A) = A #A

L(B) = B + A + A #BA

L(D) = D + BA + CA + BC #DBCA

L(F) = F + DBCA + ECA + DE #FDBECA

L(G) = G + ECA + E #GECA

L(H) = H + GECA + FDBECA + GF #HGFDBECA

最终结果

H->G->F->D->B->E->C->A

打印结果

(<class __main__.H>, <class __main__.G>, <class __main__.F>, <class __main__.D>, <class __main__.B>, <class __main__.E>, <class __main__.C>, <class __main__.A>, <class object>)

super

super()可以帮我们执行MRO中下一个父类的方法. 

class Base1:
    def chi(self):
        print("我是Base1")
class Base2:
    def chi(self):
        print("我是Base2")
class Base3:
    def chi(self):
        print("我是Base3")
class Bar(Base1,Base2,Base3):
    def chi(self):
        print("我是Bar1")
        super(Bar,self).chi()
        print("我是Bar2")
b = Bar()
b.chi()
print(Bar.__mro__)

 打印

我是Bar1
我是Base1
我是Bar2
(<class __main__.Bar>, <class __main__.Base1>, <class __main__.Base2>, <class __main__.Base3>, <class object>)

面试题

class Init(object):
    def __init__(self, v): 
        print("init")
        self.val = v

class Add2(Init):
    def __init__(self, val): 
        print("Add2")
        super(Add2, self).__init__(val) 
        print(self.val)
        self.val += 2

class Mult(Init):
    def __init__(self, val):
        print("Mult")
        super(Mult, self).__init__(val) # Haha
        self.val *= 5

class HaHa(Init):
   def __init__(self, val):
        print("哈哈")
        super(HaHa, self).__init__(val) # Init
        self.val /= 5

class Pro(Add2,Mult,HaHa): 
    pass

class Incr(Pro): 
    def __init__(self, val):
        super(Incr, self).__init__(val) 
        self.val += 1

a = Incr(5)
print(a.val)
b = Add2(2)
print(b.val)

打印

Add2
Mult
哈哈
init
5.0
8.0
Add2
init
2
4

 结论

不管super()写在哪儿. 在哪儿执行. 一定先找到MRO列表. 根据MRO列表的顺序往下找. 否则一切都是错的

以上是关于6.MRO和C3算法的主要内容,如果未能解决你的问题,请参考以下文章

有人可以解释啥是 SVN 平分算法吗?理论上和通过代码片段[重复]

片段(Java) | 机试题+算法思路+考点+代码解析 2023

mro和c3 算法

多继承c3算法与网路编程

Python多继承解析顺序的C3线性算法流程解析

Python的多继承问题-MRO和C3算法