Python在2.2引入了New-style object(ref),而且在2.3引入了新的方法解释顺序(Method resolution order,以下简称MRO),新的MRO解决了多继承下的方法解释顺序问题。
考虑如下代码:
class BaseBase: def foo(self): print 'BaseBase' class Base1(BaseBase): pass class Base2(BaseBase): def foo(self): print 'Base2' class MyClass(Base1, Base2): pass o = MyClass() o.foo() // prints 'BaseBase'
因为在Old-style object,方法解释顺序是“深度优先且从左往右”,MyClass解释foo方法时,在Base1(左边这路)找到BaseBase,就返回BaseBase的foo方法了。这跟从最近的继承层次开始找的直觉不同。
对于New-style object,引用了C3解释方法:
定义一个列表的头和尾部。对于列表[C1, C2, C3],其头是C1,尾是[C2, C3]。(熟悉函数式编程的同学应该不陌生)
C3方法公式如下:
L[MyClass(Base1, Base2)] = MyClass + merge(L[Base1], L[Base2], Base1, Base2)
其中L为类的线性化继承层次
Merge算法是:
1. 取第一个列表的头(即L[Base1][0]),如果这个头没有出现在任何列表的尾部,就把它加到L[MyClass]中,并从合并中的列表删除;否则查找下一个列表的头,作同样的判断。
2. 如果所有类都被删除,则算法成功完成;如果不能找到符合条件的列表头(好的表头),则失败,Python拒绝创建MyClass类
通过类的__mro__可以看到类的MRO列表
In [13]: MyClass.__mro__ Out[13]: (<class '__main__.MyClass'>, <class '__main__.Base1'>, <class '__main__.Base2'>, <class '__main__.BaseBase'>, <type 'object'>)
对于很多更复杂的情形,附录文档有更详尽的解释
参考文档:
The Python 2.3 Method Resolution Order