我正在阅读Python 2.3 MRO文章,其中给出了以下类层次结构:
>>> O = object
>>> class F(O): pass
>>> class E(O): pass
>>> class D(O): pass
>>> class C(D,F): pass
>>> class B(E,D): pass
>>> class A(B,C): pass
6
---
Level 3 | O |
/ --- \
/ | \
/ | \
/ | \
--- --- ---
Level 2 2 | E | 4 | D | | F | 5
--- --- ---
\ / \ /
\ / \ /
\ / \ /
--- ---
Level 1 1 | B | | C | 3
--- ---
\ /
\ /
---
Level 0 0 | A |
---
在其后面的段落中,以下引用让我感到困惑:
A lazy programmer can obtain the MRO directly from Python 2.2, since in this case it coincides with the Python 2.3 linearization.
>>> A.mro() (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.F'>, <type 'object'>)
我感到困惑的原因是文章前面提到:
Classic classes maintain their old method resolution order, depth first and then left to right.
问题:如果旧式MRO是深度优先、从左到右,那么上述类层次结构的旧式MRO应该是不同的,即ABEODOCDOFO。因此,“懒程序员”无法直接从Python 2.2获取其MRO。是这样吗?
例如,在以下代码片段中(不要在 Python 3.x 上运行它):
class O:
x = 'o'
class F(O): pass
class E(O): pass
class D(O): pass
class C(D,F):
x = 'c'
class B(E,D): pass
class A(B,C): pass
print A.x
如果旧式 MRO 与新式 MRO 相同(即 ABEC 等),我希望它打印 c
。但是,它会打印 o
(即 ABEO 等)。
或者在这里:
class O: pass
class F(O): pass
class E(O): pass
class D(O):
x = 'd'
class C(D,F):
x = 'c'
class B(E,D): pass
class A(B,C): pass
print A.x
如果旧式 MRO 与新式 MRO 相同(即 ABEC 等),我希望它打印 c
。但是,它会打印 d
(即,它是 ABEOD 等)。
我是 Python 新手,所以我想我错过了一些东西?
最佳答案
问题是,无论是在 Python 2.2、2.3 还是更高版本中,这些都是新式类。这里有3个方法解析方案,而不是2个:
- 经典类方法解析。
- Python 2.2 新式类方法解析。
- Python 2.3+ C3 线性化。
方案 2 和 3 将为给定示例生成相同的 MRO。
如果你想查看(现在几乎完全不相关的)Python 2.2 方法解析方案,最完整的文档可能是 a blog post来自 Guido 的旧 Python 历史博客。还有一个old archived draft Python 2.2 的文档,其中大部分描述了它,但没有提及特殊情况。
关于python - 对于旧式和新式,该类层次结构的 MRO 是否相同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49614553/