一、多重继承
1、MRO概念
mro 是一个列表,列表中是根据c3算法记录的,当前class,所有可以继承的按照继承优先级排序的一个线性列表。
通过class.__mro__.可以进行查询。
c3 算法详解可以查看https://www.cnblogs.com/whatisfantasy/p/6046991.html。总结起来,其实就是将当前类,和当前类的父类的,所有的mro列表进行了一个组合,按照规则 ,将所有类的mro,按照深度查找,然后,当出现两个相同的类时,保留后一个的规则,排出,
每一个类的mro, 然后进行排序。基本的原则的就是当前类的继承顺序不能与父类的继承顺序发生冲突的原则,进行一个重新排序。这个就是一个cs的一个算法。
,进行一个排序。
二,关于广度优先和深度优先
2.1深度优先
深度优先的说法只有2.1以上的版本,是基于经典类,来计算当前的类的MRO
class A:
pass 这种不需要继承object的这种称之为经典类
基于上图中每一个大写字母都是一个类,用代码展现就是
class A:
name='eric'
class B(A):
pass
class C(A):
name = 'ren'
class D(B ,C):
pass
此是,D实例化一个对象obj = D() ,这个obj 需要调用name属性,如果是深度优先,查找逻辑就是D、B、A、C、A。所以此时调用到的就是name=‘eric’ ,但是实际上,C类中的属性,已经对此属性进行了重新赋值,或者添加了新的内容,所以我们希望
看到调用的是C下面的name属性。所以此时产生的mro,这个继承顺序列表是不合理的。 这也就是所谓的深度优先
2.2
为了解决这种问题,加上python内部的改进,出现了新式类,也就是
class B(object):
pass
这种继承object 称之为新式类,在目前的3.0版本的python中只存在新式类
基于上图进行代码实现
class A(object):
name = 'eric'
class B(A):
pass
class C(A):
name ='ren'
class D(B):
pass
class E(C):
pass
class F(D,E):
pass
这个时候,在用obj = F() 实例化一个实例,在来调用name这个属性 , obj.name ,这个时候 就会根据广度优先 ,查找顺序是F、D、B、E、C、A。根据c3算法,产生一个根据这种排序的mro ,同样可以通过class.__mro__进行查看。
三、根据mro来判断,调用属性或者调用方法
所以当我们进行查找是的一个顺序是,优先查找当前类,然后查找继承的类,当继承多个类时,按照从左到右进行查找。当我们出现两个类继承同一个父类时,先按照广度优先,查找后,最后在查找父类。
这种查找顺序,无论是方法还是属性都是一致。
ps:例子
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
class A:
def bar(self):
print("BAR")
self.f1()
class B(A):
def f1(self):
print("B")
class C:
def f1(self):
print("C")
class D(C, B):
pass
obj = D()
obj.bar()
结果
BAR
C