python的MRO和C3算法

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

class A(object):
    def test(self):
        print(‘from A‘)

class B(A):
    def test(self):
        print(‘from B‘)

class C(A):
    def test(self):
        print(‘from C‘)

class D(B):
    def test(self):
        print(‘from D‘)

class E(C):
    def test(self):
        print(‘from E‘)

class F(D,E):
    # def test(self):
    #     print(‘from F‘)
    pass
f1=F()
f1.test()
print(F.__mro__) #只有新式才有这个属性可以查看线性列表,经典类没有这个属性
#新式类继承顺序:F->D->B->E->C->A
#经典类继承顺序:F->D->B->A->E->C

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

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 I:
    pass
class J(B, C):
    pass
class K(A):
    pass
class H(I, J, K):
    pass
class Foo(H, G):
    pass
print(Foo.__mro__)
结果
Foo -->H-->I-->J-->G-->F-->D-->B-->C-->K-->A-->E-->‘object‘

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

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 M:
    pass
class N(M):
    pass
class P(E, A):
    pass
class X:
    pass
class Q(P,N,X):
    pass
class G(Q, F):
    pass
class H(G, F):
    pass

加法:merge(),拿第一项的第一位和后面项除了第一位的每位比较,如果没有出现,则该位元素算出
如果出现了,此时开始下一项的第一位继续和后面项除了第一位的每一位比较,
如果后边项里除了第一位的其他位出现有,则继续开始拿下一项的第一位和后一项除了第一位的其他位做比较
如果后边项没有出现,取完这一项的第一位后,重新返回第一项继续执行判断第一项的第一位与后边项除了第一位比较

比如
F + DBCA + ECA + DE
DBCA + ECA + DE
BCA + ECA + E
CA + CA
A + A

思路:
第一次拿第一项的第一位F与DBCA,ECA,DE比较,这三个数除了第一位后面的每一项都没有F出现,
所以把所有的F消除,取值F
第二次拿第二项DBCA的第一位D与ECA,DE比较,这两数中除了第一位后边的每一项都没有D出现,
所以就把所有的D消除,然后取值D
第三次拿第二项BCA的B与ECA,E比较,这两个数中除了第一位后边的每一项都没有B出现,
所以就把所有的B消除,取值B
第四次拿第二项CA的C与ECA,E比较,ECA出现了C,所以不动CA,然后拿下一项的ECA的第一位E与最后一项的值E做比较,
因为ECA的E重复了最后一项E,所以也不动ECA,然后拿最后一项的E与后边作比较,因为后边没项值,
所以消除所有的E,取值E
第四次拿返回开头拿第二项CA中的C与后边的项CA做比较,因为后边项中除了第一位,其他位没有C,
所以消除所有的C,取值C
第五次拿第二项的A与后边的项A做比较,因为后边项值有A,所有拿后边项A与后边项做比较,因为后边项没有值,
所以消除所有的A,取值A
结果
FDBECA

求H的MRO
设求MRO的算法是L
解析步骤:
                                    拆分                          合并
L(H) = H + L(G) + L(F) + GF #H + GQPFDBECANMX + FDBECA + GF = HGQPFDBECANMX
L(G) = G + L(Q) + L(F) + QF #G + QPECANMX + FDBECA + QF = GQPFDBECANMX
L(Q) = Q + L(P) + L(N) + L(X) + PNX #Q + PECA + NM + X + PNX = QPECANMX
L(X) = X    #X
L(P) = P + L(E) + L(A) + EA #P + ECA + A + EA = PECA
L(N) = N + L(M) + M     #N + M + M = NM
L(M) = M    #M
L(F) = F + L(D) + L(E) + DE #F + DBCA + ECA + DE = FDBECA
L(E) = E + L(C) + L(A) + CA #E + CA + A + CA = ECA
L(D) = D + L(B) + L(C) + BC #D + BA + CA + BC = DBCA
L(C) = C + L(A) + A     #C + A + A = CA
L(B) = B + L(A) + A     #B + A + A = BA
L(A) = A    #A
所以结果是
HGQPFDBECANMX

和电脑运算的结果一致
print(H.__mro__)

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("我是Bar里面的chi1")
        # super(类名, self)  从某个类开始找下一个MRO
        super(Base2, self).chi()    # 此时调用的super. 在Bar调用 -> super表示找MRO里的下一个
        # super().chi() # super(Bar, self).chi()
        print("我是Bar里面的chi2")

b = Bar()   # Bar, Base1, Base2, Base3, object
b.chi()
print(Bar.__mro__)

结果:
我是Bar里面的chi1
我是Base3
我是Bar里面的chi2
(<class ‘__main__.Bar‘>, <class ‘__main__.Base1‘>, <class ‘__main__.Base2‘>, <class ‘__main__.Base3‘>, <class ‘object‘>)

事例2
class Base1:
    def chi(self):
        super().chi()
        print("我是Base1")

class Base2:
    def chi(self):
        super().chi()
        print("我是Base2")

class Base3:
    def chi(self):
        print("我是Base3")

class Bar(Base1, Base2, Base3):
    def chi(self):
        print("我是Bar里面的吃1")
        super(Bar, self).chi()
        print("我是Bar里面的吃2")

b = Bar()
b.chi()

结果
我是Bar里面的吃1
我是Base3
我是Base2
我是Base1
我是Bar里面的吃2

MRO + super 面试题

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)
        self.val *= 5

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

class Pro(Add2,Mult,HaHa):
    pass

class Incr(Pro):    # incr->pro->add2->Mult->HaHa->init
    def __init__(self, val):
        super(Incr, self).__init__(val)
        self.val += 1
p = Incr(5)
print(p.val)

原文地址:https://www.cnblogs.com/wangm-0824/p/10199647.html

时间: 2024-11-08 06:36:01

python的MRO和C3算法的相关文章

mro之C3算法

mro之C3算法 # C3算法 归并算法 class A(object): pass class B(A): pass class C(A): pass class D(B): pass class E(C): pass class F(D, E): pass print(F.__mro__) ######################### # 第一步先找到继承的父类的MRO # D = [D, B, A, O] # E = [E, C, A, O] # 第二步 把父类这两个MRO 和 DE

python中的MRO和C3算法

一. 经典类和新式类 1.python多继承 在继承关系中,python子类自动用友父类中除了私有属性外的其他所有内容.python支持多继承.一个类可以拥有多个父类 2.python2和python3的区别 python2中存在两种类,一个叫经典类,在python2.2之前,一直使用的经典类.经典类是在基类的根如果什么都不写.表示继承xxx 另一个叫做心事类,在python2.2之后出现了心事类.新式类的特点是基类的根是object python3中使用的都是新式类.如果基类谁都不继承,那这个

16 继承 MRO和C3算法

一 多继承 Python中类与类之间可以有继承关系. 当出现了了x是一种y的的时候. 就可以使用继承关系. 即"is-a" 关系.  在继承关系中. 子类自动拥有父类中除了了私有属性外的其他所有内容.  python支持多继承. 一个类可以拥有多个父类. class ShenXian: # 神仙 def fei(self): print("神仙都会飞") class Monkey: # 猴 def chitao(self): print("猴?喜欢吃桃子&

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,从左往右的顺序 新式

21 MRO C3算法

三十九 MRO 多继承的继承顺序 一.python2.2之前用的是   经典类的MRO继承 ①深度递归继承     从左到右 ,一条路走到黑 ②广度继承           一层一层的继承 深度继承时   为   R 1 2 3 4 5 6 广度继承时  为    R 1 4 2 3  5 6 二.python2.2 之后用的是      新式的MRO继承    C3算法 1.拆分 2.合并 拆分 合并 直接打印时 三.  super( ).方法          找MRO  顺序的下一项 su

Python基础13_类与类型, MRO, C3算法, super()

一. python多继承 类与类型:http://www.cnblogs.com/blackmatrix/p/5594109.html 子类继承了多个父类, 当父类出现了重名方法时, 这时就涉及到查找父类方法的问题, 即MRO(method resolution order)问题 python中有两种类, 经典类和新式类 在Python2及以前的版本中,由任意内置类型派生出的类(只要一个内置类型位于类树的某个位置),都属于"新式类",都会获得所有"新式类"的特性:反

python的继承,多继承,经典类的MRO,新式类的MRO,C3算法,super

#继承 class JiaoFu: def qd(self): print("教父带你祈祷") class Fu: def msj(self): print("alex喜欢msj") class Zi(Fu, JiaoFu): def dbj(self): print("刘伟喜欢大宝剑") z = Zi() z.msj() z.dbj() z.qd() class Base1: # Base1 object def func(self): pri

Python新式类继承的C3算法

在Python的新式类中,方法解析顺序并非是广度优先的算法,而是采用C3算法,只是在某些情况下,C3算法的结果恰巧符合广度优先算法的结果. 可以通过代码来验证下: class NewStyleClassA(object): var = 'New Style Class A' class NewStyleClassB(NewStyleClassA): pass class NewStyleClassC(NewStyleClassA): var = 'New Style Class C' class

python的垃圾回收机制 继承的顺序C3算法

Python垃圾回收    -- 引用计数        -- Python为每个对象维护一个引用计数        -- 当引用计数为0的 代表这个对象为垃圾    -- 标记清除        -- 解决孤立的循环引用        -- 标记根节点和可达对象        -- 不可达视为垃圾    -- 分代回收        -- 解决标记清除的效率问题        -- 0代 1代 2代        -- 阈值 (700,10,10)        -- 当调用c的接口开辟内存和