class A: def test(self): print("AAA-test") class B: def test(self): print("BBB-test") # 继承了三个类,B、A、还有默认继承的 object class C(B, A): ... # 通过类对象调用,不是实例对象! print(C.__mro__) # 输出结果 (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
其实 MRO 是涉及一个底层算法的,下面来详细讲解一下
Python 发展到现在经历了三种算法
https://www.cnblogs.com/poloyy/p/15226425.html
https://www.python.org/download/releases/2.3/mro/
需要在 python2 环境下运行这段代码
# 旧式类算法 class A: def test(self): print("CommonA") class B(A): pass class C(A): def test(self): print("CommonC") class D(B, C): pass D().test() # python2 下的运行结果 CommonA
虽然解决了旧式 MRO 算法的问题,但可能会违反单调性原则
在子类存在多继承时,子类不能改变父类的 MRO 搜索顺序,否则会导致程序发生异常
class X(object): pass class Y(object): pass class A(X, Y): pass class B(Y, X): pass class C(A, B): pass
分析不同类的 MRO
很明显,B、C 中间的 X、Y 顺序是相反的,就是说 B 被继承时,它的搜索顺序会被改变,违反了单调性
class A: def test(self): print("CommonA") class B(A): pass class C(A): def test(self): print("CommonC") class D(B, C): pass D().test() # 输出结果 CommonC
以上面代码为栗子,C3 会把各个类的 MRO 等价为以下等式
以 A 类为栗,merge() 包含的 A 成为 L[A] 的头,剩余元素(这里只有 object)称为尾
重复以上步骤直到列表为空,则算法结束;如果不能再找出可以输出的元素,则抛出异常
class B(object): pass print(B.__mro__) (<class '__main__.B'>, <class 'object'>)
L[B] = L[B(object)] = B + merge(L[object]) = B + L[object] = B object
# 计算 MRO class B(object): pass class C(B): pass print(C.__mro__) (<class '__main__.C'>, <class '__main__.B'>, <class 'object'>)
L[C] = C + merge(L[B]) = C + L[B] = C B object
O = object class F(O): pass class E(O): pass class D(O): pass class C(D, F): pass class B(D, E): pass class A(B, C): pass print(C.__mro__) print(B.__mro__) print(A.__mro__) # 输出结果 (<class '__main__.C'>, <class '__main__.D'>, <class '__main__.F'>, <class 'object'>) (<class '__main__.B'>, <class '__main__.D'>, <class '__main__.E'>, <class 'object'>) (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.E'>, <class '__main__.F'>, <class 'object'>)
L[O] = O = object
L[D] = D + merge(L[O]) = D O
L[C] = L[C(D, F)] = C + merge(L[D], L[F], DF) # 从前面可知 L[D] 和 L[F] 的结果 = C + merge(DO, FO, DF) # 因为 D 是顺序第一个并且在几个包含 D 的 list 中是 head, # 所以这一次取 D 同时从列表中删除 D = C + D + merge(O, FO, F) # 因为 O 虽然是顺序第一个但在其他 list (FO)中是在尾部, 跳过 # 改为检查第二个list FO # F 是第二个 list 和其他 list 的 head # 取 F 同时从列表中删除 F = C + D + F + merge(O) = C D F O
L[B] = L[B(D, E)] = B + merge(L[D], L[E], DE) = B + merge(DO, EO, DE) = B + D + merge(O, EO, E) = B + D + E + merge(O) = B D E O
L[A] = L[A(B,C)] = A + merge(L[B], L[C], BC) = A + merge( BDEO, CDFO, BC ) = A + B + merge( DEO, CDFO, C ) # D 在其他列表 CDFO 不是 head,所以跳过到下一个列表的 头元素 C = A + B + C + merge( DEO, DFO ) = A + B + C + D + merge( EO, FO ) = A + B + C + D + E + merge( O, FO ) = A + B + C + D + E + F + merge( O ) = A B C D E F O