方法解析顺序, 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__
输出:
(, , , )
可以看到, 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对象的属性访问过程).
补充知识:python中的单继承,多继承和mro顺序
python作为一门动态语言,是和c++一样支持面向对象编程的。相对对象编程有三大特性,分别是继承,封装和多态。今天我们重点讲解的是,python语言中的单继承和多继承。
继承概念:
如果一个类继承了另外一个类时,它将自动获得另一个类的所有属性和方法,那么原有的类称为父类,而新类称为子类。子类继承了其父类的所有属性和方法。同时还可以定义自己的属性和方法。
单继承就是一个子类只能继承一个父类。
格式: class 子类(父类)
举例: class A(B)
A类拥有了B类的所有的特征,A类继承了B类
B类 父类,基类
A类 子类 派生类 后代类
继承的作用:功能的升级和扩展
功能的升级就是对原有 的功能进行完善重新,功能的扩展就是对原本没有的功能进行添加。减少代码的冗余。
下面我们举一个单继承的例子:
class Dog(): #父类
def __init__(self): #父类的属性初始化
self.name='狗'
self.leg=4
def __str__(self):
return "名字:%s %d 条腿"%(self.name,self.leg)
class Taidi(Dog): #定义一个Taidi 泰迪 类继承自Dog类 -->单继承
pass
taidi=Taidi()
print(taidi) 输出结果--> 名字:狗 4 条腿