标签:关系 erp height text 复杂 就是 class vertica 面向对象语言
这种继承结构下导致的问题称之为菱形问题:如果A中有一个方法,B和/或C都重写了该方法,而D没有重写它,那么D继承的是哪个版本的方法:B的还是C的?如下所示
class A(object):
def test(self):
print(‘from A‘)
?
?
class B(A):
def test(self):
print(‘from B‘)
?
?
class C(A):
def test(self):
print(‘from C‘)
?
?
class D(B,C):
pass
?
?
obj = D()
obj.test() # 结果为:from B
一、继承原理(MRO)
python到底是如何实现继承的呢? 对于你定义的每一个类,Python都会计算出一个方法解析顺序(MRO)列表,该MRO列表就是一个简单的所有基类的线性顺序列表,如下
>>> D.mro() # 新式类内置了mro方法可以查看线性列表的内容,经典类没有该内置该方法
[<class ‘__main__.D‘>, <class ‘__main__.B‘>, <class ‘__main__.C‘>, <class ‘__main__.A‘>, <class ‘object‘>]
python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。 而这个MRO列表的构造是通过一个C3线性化算法来实现的。我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
1.子类会先于父类被检查
2.多个父类会根据它们在列表中的顺序被检查
3.如果对下一个类存在两个合法的选择,选择第一个父类
所以obj.test()的查找顺序是,先从对象obj本身的属性里找方法test,没有找到,则参照属性查找的发起者(即obj)所处类D的MRO列表来依次检索,首先在类D中未找到,然后再B中找到方法test
1.由对象发起的属性查找,会从对象自身的属性里检索,没有则会按照对象的类.mro()规定的顺序依次找下去,
2.由类发起的属性查找,会按照当前类.mro()规定的顺序依次找下去,
二、深度和广度的优先级
非菱形结构:
参照下述代码,多继承结构为非菱形结构,此时,会按照先找B这一条分支,然后再找C这一条分支,最后找D这一条分支的顺序直到找到我们想要的属性
class E:
def test(self):
print(‘from E‘)
?
?
class F:
def test(self):
print(‘from F‘)
?
?
class B(E):
def test(self):
print(‘from B‘)
?
?
class C(F):
def test(self):
print(‘from C‘)
?
?
class D:
def test(self):
print(‘from D‘)
?
?
class A(B, C, D):
# def test(self):
# print(‘from A‘)
pass
?
?
print(A.mro())
‘‘‘
[<class ‘__main__.A‘>, <class ‘__main__.B‘>, <class ‘__main__.E‘>, <class ‘__main__.C‘>, <class ‘__main__.F‘>, <class ‘__main__.D‘>, <class ‘object‘>]
‘‘‘
?
obj = A()
obj.test() # 结果为:from B
# 可依次注释上述类中的方法test来进行验证
菱形结构:
经典类————》python2
如果继承关系为菱形结构,那么经典类与新式类会有不同MRO,分别对应属性的两种查找方式:深度优先和广度优先
class G: # 在python2中,未继承object的类及其子类,都是经典类
def test(self):
print(‘from G‘)
?
class E(G):
def test(self):
print(‘from E‘)
?
class F(G):
def test(self):
print(‘from F‘)
?
class B(E):
def test(self):
print(‘from B‘)
?
class C(F):
def test(self):
print(‘from C‘)
?
class D(G):
def test(self):
print(‘from D‘)
?
class A(B,C,D):
# def test(self):
# print(‘from A‘)
pass
?
obj = A()
obj.test() # 如上图,查找顺序为:obj->A->B->E->G->C->F->D->object
# 可依次注释上述类中的方法test来进行验证,注意请在python2.x中进行测试
新式类————》python3
class G(object):
def test(self):
print(‘from G‘)
?
class E(G):
def test(self):
print(‘from E‘)
?
class F(G):
def test(self):
print(‘from F‘)
?
class B(E):
def test(self):
print(‘from B‘)
?
class C(F):
def test(self):
print(‘from C‘)
?
class D(G):
def test(self):
print(‘from D‘)
?
class A(B,C,D):
# def test(self):
# print(‘from A‘)
pass
?
obj = A()
obj.test() # 如上图,查找顺序为:obj->A->B->E->C->F->D->G->object
# 可依次注释上述类中的方法test来进行验证
总结:
多继承到底要不用???
要用,但是规避几点问题
1、继承结构尽量不要过于复杂
2、推荐使用mixins机制:在多继承的背景下满足继承的什么"是"什么的关系
标签:关系 erp height text 复杂 就是 class vertica 面向对象语言
原文地址:https://www.cnblogs.com/bailongcaptain/p/12670533.html