这个类层次结构的MRO对于oldstyle和newstyle是相同的吗?

2024-06-14 20:08:03 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在阅读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。因此,“懒惰的程序员”不能直接从Python2.2获得MRO。是这样吗?你知道吗

例如,在以下代码段上(不要在Python3.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(即,它是abood等)。你知道吗

我是Python新手,所以我想我错过了什么?你知道吗


Tags: theobject层次结构main文章样式passlevel
3条回答

问题是,无论是在python2.2、2.3还是更高版本中,这些都是新样式的类。这里有3方法分辨率方案,而不是2:

  1. 经典类方法解析。你知道吗
  2. python2.2新型类方法解析。你知道吗
  3. Python 2.3+C3线性化。你知道吗

方案2和方案3将为给定的示例生成相同的MRO。你知道吗

如果您想查看(现在几乎完全不相关的)python2.2方法解析方案,最完整的文档可能是Guido的老Python历史博客中的a blog post。还有一个old archived draft的python2.2文档,主要描述了它,但没有提到一个特殊的情况。你知道吗

the blog post from Guido(2010年6月),特别是这一重要细节:

The computation of the MRO was officially documented as using a depth-first left-to-right traversal of the classes as before. If any class was duplicated in this search, all but the last occurrence would be deleted from the MRO list.

所以你有ABEODOCDOFO,是的,但是那些更早的O被删除了!你知道吗

Guido编写的“官方文档”声明不是来自您问题中链接的2.3MRO页面,而是来自旧的2.2 MRO page,您将发现其中提到:

Using the classic lookup rule, construct the list of classes that would be searched, including duplicates. Now for each class that occurs in the list multiple times, remove all occurrences except for the last.

旧样式的类没有内置的mro方法;只有新样式的类才有。你知道吗

另外,请注意,实际示例中有O = object,而不是class O: pass,生成这些新样式的类。你知道吗

这个例子是读者练习的一部分。你知道吗

所以这一段只是说,一个懒惰的程序员如果不想完成示例中的练习,并且还没有访问2.3解释器的权限,可以将此代码粘贴到2.2解释器中,调用A.mro()并得到答案,因为这种情况恰好是2.2和2.3新样式的类规则给出相同的结果回答。你知道吗

相比之下,一个不懒惰的程序员,当他们给出相同的答案和不给出相同的答案时,会想学习,而不是仅仅依赖于他们有时会给出相同答案的事实。你知道吗

相关问题 更多 >