也可以在我的博客阅读:https://jiajunhuang.com/articles/2019_05_29-python_old_new_style_class.md.html
Python2.3之前,使用的是老式继承,直接看例子:
>>> O = object
>>> class X(O): pass
>>> class Y(O): pass
>>> class A(X,Y): pass
>>> class B(Y,X): pass
这样下来,方法查找链就是这样的:
-----------
| |
| O |
| / \ |
- X Y /
| / | /
| / |/
A B
\ /
?
因此,不能再有一个新的类来继承 A 和 B,因为 A 的继承顺序是 X-Y,而 B 的继承顺序是 Y-X,那么到底是先在 X 里查找还是先在 Y 里查找呢?
为了解决这个问题,引入了 C3 MRO,还是以例子来说明:
>>> 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
那么方法查找链是这样:
6
---
Level 3 | O | (more general)
/ --- \
/ | \ |
/ | \ |
/ | \ |
--- --- --- |
Level 2 3 | D | 4| E | | F | 5 |
--- --- --- |
\ \ _ / | |
\ / \ _ | |
\ / \ | |
--- --- |
Level 1 1 | B | | C | 2 |
--- --- |
\ / |
\ / \ /
---
Level 0 0 | A | (more specialized)
---
计算的时候就是:
L[O] = O
L[D] = D O
L[E] = E O
L[F] = F O
L[B] = B + merge(DO, EO, DE)
规则就是,以继承时的声明为顺序,每次取方法查找链的头一个,如果这个头不在后面的方法查找链的尾部,那么就把他放到方法查找链
里,首先方法查找肯定是在 B 里进行,然后是 merge(DO, EO, DE),D 是一个好的节点,因为 D 不在 DO, EO, DE 的尾部。然后是
O,O 在 EO 的尾部。然后是 E ,然后是 O 。
所以最后方法查找链就是 B -> D -> E -> O。
同样,拿上面的例子来看,C3 MRO的查找顺序就应该是 A -> X -> Y -> B -> O
参考资料:
本文介绍了Python中新式类(new style class)和老式类(old style class)的区别,主要关注在方法解析顺序(C3 MRO)上的不同。通过例子展示了C3 MRO如何解决多重继承时的方法查找问题,确保了查找顺序的一致性和避免了二义性。

被折叠的 条评论
为什么被折叠?



