Python中的多继承与MRO

与大多数语言相同,Python支持多继承,其声明方式也很简单:class Child(Parent1, Parent2, Parent3...)
提到多继承,就必须要说一下经典的菱形继承关系。如下图

Python中的多继承与MRO_第1张图片
多继承UML

代码部分如下:

class A(object):
    def getvalue(self):
        print 'getvalue from A'
    def show(self):
        print 'show from A'

class B(A):
    def getvalue(self):
        print 'getvalue from B'

class C(A):
    def getvalue(self):
        print 'getvalue from C'
    def show(self):
        print 'show from C'

class D(B, C):
    pass

d = D()
d.getvalue()
d.show()

上面这段代码的执行结果是getvalue from Bshow from C
这就牵扯到Python中多继承时,MRO(Method Resolution Order 方法解析顺序)的实现了。
Python中的MRO大概是下面的策略:

  1. 由c1,c2...cn表示类c1至cn的序列,而对于c的继承顺序是b1,b2...bn,L[c]表示c的线性继承关系,L[object]=object。
  2. 具体实现是:L[C(b1b2...bn)] = c + merge(L[b1],L[b2]...L[bn], b1...bn)
    3.其中merge的计算是:在L[b1]L[bn],b1...bn中,取L[b1]所继承的第一个基类,若果这个类不在L[b2]...L[bn],b1...bn的序列中,则把这个类加入到线性继承序列中,同时将其出队。

结合上面的代码实例,可以得到下面的计算过程(O是object的简写):

L[O] = O
L[A]=A, O
L[B] = B + merge(L[A])
       = B + merge(A, O)
       = B + A + merge(O, O)
       = B, A, O
L[C] = C + merge(L[A])
        = C + merge(A, O)
        = C + A + merge(O, O)
        = C, A, O
L[D] = D + merge(L[B], L[C], BC)
        = D + merge(BAO, CAO, BC)
        = D + B + merge(AO, CAO, C)
        = D + B + C + merge(AO, AO)
        = D+B+C+A+O
        = D, B, C, A, O

所以,在D的实例d中执行方法是,寻找的顺序使D->B->C->A->O,这个顺序可以通过print d.__mro__直接验证。
相同的,不仅是类方法,类属性的查找顺序也遵循MRO。

简单来说,菱形继承是一种多继承的情景,但它的MRO有时候可能并不是我们所期待的样子。所以,在实际代码中要尽可能去避免菱形继承的情景出现。

你可能感兴趣的:(Python中的多继承与MRO)