Python多重继承(拓扑排序)(9)

Python跟Java不同,Java只能单继承(不过有多实现),而Python能够多重继承。其多重继承遵循拓扑排序。

关于拓扑排序,首先我们看下面这张有向无环图(字面意思,按照箭头方向,不存在一个环):

Python多重继承(拓扑排序)(9)_第1张图片
有向无环图.png

把该图当成Python的子父类继承图,E就是最顶级的父类,CD继承E,A继承CD,B继承D,S继承AB。按照拓扑排序规则,步骤如下:

  1. 寻找入度为0的顶点,即没有箭头指向的顶点,该图为S。
  2. 拿掉S顶点,入度为0的顶点有A和B,遵循最左原则,入度为0的顶点为A。
  3. 拿掉A顶点,入度为0的顶点有B和C,遵循最左原则,入度为0的顶点为C。
  4. 拿掉C顶点,入度为0的顶点为B。
  5. 拿掉B顶点,入度为0的顶点为D。
  6. 拿掉D顶点,入度为0的顶点为E。

最后,该有向无环图的拓扑排序为:S, A, C, B, D, E。

当子类多重继承时,所有父类(父父类等)当中有相同的方法,子类实例调用该方法时,到底调用的是哪个父类的方法呢?这时候就需要拓扑排序了。拥有该方法的父类当中哪个靠前,调用的就是哪个父类的方法。

下面看代码示例:

class E(object):
    def foo(self):
        print('E foo')

    def bar(self):
        print('E bar')


class C(E):
    def foo(self):
        print('C foo')

    def bar(self):
        print('C bar')


class D(E):
    pass


class A(C, D):
    def bar(self):
        print('A-bar')


class B(D):
    pass


class S(A, B):
    pass


# 拓扑排序为:S, A, C, B, D, E。所以s.foo()调用的是C类的foo方法,s.bar()调用的是A类的bar方法
# S.__mro__可以输出拓扑排序的结果。
if __name__ == '__main__':
    print(S.__mro__)
    s = S()
    s.foo()
    s.bar()

你可能感兴趣的:(Python多重继承(拓扑排序)(9))