我正在阅读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 |
---
在其后的段落中,以下引用使我感到困惑:
懒惰的程序员可以直接从Python 2.2获取MRO,因为
在这种情况下,它与Python 2.3线性化一致。
>>> A.mro()
(<class '__main__.A'>, <class '__main__.B'>, <class '__main__.E'>,
<class '__main__.C'>, <class '__main__.D'>, <class '__main__.F'>,
<type 'object'>)
我感到困惑的原因是在文章的前面已经说过:
经典类保持其旧方法的解析顺序,深度
首先,然后从左到右。
问题:如果旧式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方法解析方案,则最完整的文档可能来自Guido的旧Python历史博客中的a blog post。还有一个关于Python 2.2的文档old archived draft,主要描述了它,但是没有提及特殊情况。
关于python - 对于旧样式和新样式,该类层次结构的MRO是否相同?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49614553/