Python跟Java不同,Java只能单继承(不过有多实现),而Python能够多重继承。其多重继承遵循拓扑排序。
关于拓扑排序,首先我们看下面这张有向无环图(字面意思,按照箭头方向,不存在一个环):
有向无环图.png把该图当成Python的子父类继承图,E就是最顶级的父类,CD继承E,A继承CD,B继承D,S继承AB。按照拓扑排序规则,步骤如下:
- 寻找入度为0的顶点,即没有箭头指向的顶点,该图为S。
- 拿掉S顶点,入度为0的顶点有A和B,遵循最左原则,入度为0的顶点为A。
- 拿掉A顶点,入度为0的顶点有B和C,遵循最左原则,入度为0的顶点为C。
- 拿掉C顶点,入度为0的顶点为B。
- 拿掉B顶点,入度为0的顶点为D。
- 拿掉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()
网友评论