方法解析顺序, Method Resolution Order
从一段代码开始
考虑下面的情况:
class A(object):
def foo(self):
print('A.foo()')
class B(object):
def foo(self):
print('B.foo()')
class C(B, A):
pass
c = C()
c.foo()
C
同时继承了类A
和类B
, 它们都有各自的foo()
方法. 那么C
的实例c
调用foo()
方法时, 到底是调用A.foo()
还是B.foo()
?
__mro__
Python的每一个有父类的类都有一个与方法解析顺序相关的特殊属性:__mro__
, 它是一个tuple
, 装着方法解析时的对象查找顺序: 越靠前的优先级越高. 执行下面的代码:
print type(C.__mro__)
print C.__mro__
输出:
<type 'tuple'>
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
可以看到, B
在C
的前面, 所以在上一段代码中, c.foo()
调用的是B.foo()
而不是A.foo()
.
之所以B
在C
的前面, 是因为在指定C
的父类时先指定了B
:
class C(B, A):
若将它改成:
class C(A, B):
c.foo()
执行的就是A.foo()
了.
熟悉环境变量的可以将__mro__
理解为以目标对象为环境的PATH
变量: 从左到右开始查找, 找到就执行, 然后返回结果.
方法解析顺序
从C.__mro__
的值可以看出, Python的方法解析优先级从高到低为:
1. 实例本身(instance)
2. 类(class)
3. super class, 继承关系越近, 越先定义, 优先级越高.
其实属性解析顺序也基本一致, 只不过多了个__getattr__
的查找(见Python对象的属性访问过程).