开发者

Python 3.1: C3 method resolution order

开发者 https://www.devze.com 2023-01-14 21:46 出处:网络
A very simple case of diamond-type inheritance: class Root: def f(self): print(\'Root\') class A(Root): pass

A very simple case of diamond-type inheritance:

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()

According to Python 3.1.2 documentation:

For most purposes, in the simplest cases, you can think of the开发者_StackOverflow中文版 search for attributes inherited from a parent class as depth-first, left-to-right, not searching twice in the same class where there is an overlap in the hierarchy.

Hence, I expect my example to resolve in the order: AB -> A -> Root -> B. But it doesn't. Using ActiveState Python 3.1.2, the output is 'B' rather than 'Root'.

What am I missing?

Also, I noticed that ActiveState Python 2.6 prints 'Root' with the same code. Did the resolution rules change between 2.6 and 3.1?


Python 2.6 printed Root because Root is an old-style class. It should print B if Root inherits from object (making it a new-style class).

Old style class doesn't use the C3 MRO, but the old flawed MRO, which is exactly what your quoted text describes.


The reason B appears before Root is because B inherits from Root also.

The inheritance graph of AB is:

 AB - A - Root -- object
    \   /
      B

So:

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]

in case of multiple inheritance, the MRO is computed by taking the elements in the superclass's MROs from left to right, that doesn't appear in the middle. Better explained in example:

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] 

Further detail can be found in http://www.python.org/download/releases/2.3/mro/.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号