代码之家  ›  专栏  ›  技术社区  ›  max

python3.1:C3方法解析顺序

  •  4
  • max  · 技术社区  · 14 年前

    菱形类型继承的一个非常简单的例子:

    class Root:
        def f(self):
            print('Root')
    
    class A(Root): pass
    
    class B(Root):
        def f(self):
            print('B')
    
    class AB(A, B): pass
    
    AB().f()
    

    根据 Python 3.1.2 documentation :

    在大多数情况下,最简单的 案例,你可以想到搜索 从父级继承的属性 从左到右,按深度优先分类, 不在同一个类中搜索两次

    因此,我希望我的示例按以下顺序进行解析:AB->A->Root->B。但事实并非如此。使用ActiveState Python 3.1.2,输出是“B”而不是“Root”。

    我错过了什么?

    另外,我注意到activestatepython2.6使用相同的代码打印“Root”。决议规则在2.6和3.1之间有变化吗?

    1 回复  |  直到 14 年前
        1
  •  9
  •   kennytm    14 年前

    Python2.6打印的根目录 Root 是一个老式的班级。应该打印出来 B 如果 继承自 object (使之成为一门新型的课程)。


    B出现在Root之前的原因是B也从Root继承。

     AB - A - Root -- object
        \   /
          B
    

    所以:

    mro(object) = [object]
    mro(Root)   = [Root] + mro(object)   # mro of single-inherited class is simple...
                = [Root, object]
    mro(A)      = [A, Root, object]
    mro(B)      = [B, Root, object]
    

    在多重继承的情况下,MRO是通过将超类的MROS中的元素从左到右计算出来的,而不是出现在中间。更好的例子解释:

    mro(AB) = [AB] + merge(mro(A), mro(B))
            = [AB] + merge([A, Root, object], [B, Root, object])   
            = [AB] + [A] + merge([Root, object], [B, Root, object])
               # A appears at head, pop it.
            = [AB] + [A] + [B] + merge([Root, object], [Root, object])
               # cannot pop Root because Root is not at head of [B, Root, object]
               # pop B instead.
            = [AB] + [A] + [B] + [Root] + merge([object], [object])
               # now we can pop Root because it only appears at the head position
            = [AB] + [A] + [B] + [Root] + [object]
            = [AB, A, B, Root, object] 
    

    http://www.python.org/download/releases/2.3/mro/ .