2021年2月15日 / 7次阅读 / Last Modified 2021年2月15日
面向对象
MRO,Method Resolution Order,应该是一个比较通用的概念,具体是指在有继承关系,特别是多重继承关系的OOP代码中,子类的对象在调用继承下来的函数时,要通过MRO的顺序,去定位具体的调用位置。
class aa:
def __init__(self):
print('in aa')
def fun(self):
print('in aa fun')
class bb:
def __init__(self):
print('in bb')
def fun(self):
print('in bb fun')
class cc(aa,bb):
pass
c = cc()
c.fun()
print(cc.mro())
cc继承aa和bb,因此cc的__init__和fun函数,都需要MRO来决策具体的调用位置,因为这两个函数,在aa和bb中都存在。这段代码的运行效果如下:
in aa
in aa fun
[<class '__main__.cc'>, <class '__main__.aa'>, <class '__main__.bb'>, <class 'object'>]
按照MRO的顺序,cc的两次调用,都定位在aa内。
cc.mro()输出类cc的MRO顺序list!MRO顺序,就是代码中的书写顺序,aa写在bb前面,MRO中,aa就在bb前面!
与MRO密切相关的,是一个我们常见的super函数。
下面这段代码描述的继承关系,存在重复调用:
class aa:
def __init__(self):
print('in aa')
class bb(aa):
def __init__(self):
print('in bb')
aa.__init__(self)
class cc(aa):
def __init__(self):
print('in cc')
aa.__init__(self)
class dd(bb,cc):
def __init__(self):
print('in dd')
bb.__init__(self)
cc.__init__(self)
dd()
这段代码运行的效果:
in dd
in bb
in aa
in cc
in aa
可以看到in aa出现了两次,有重复调用。
这种场景下,使用super函数,就可以避免重复调用:
class aa:
def __init__(self):
print('in aa')
class bb(aa):
def __init__(self):
print('in bb')
super(bb, self).__init__()
class cc(aa):
def __init__(self):
print('in cc')
super(cc, self).__init__()
class dd(bb,cc):
def __init__(self):
print('in dd')
super(dd, self).__init__()
dd()
print(dd.mro())
print(cc.mro())
运行效果:
in dd
in bb
in cc
in aa
[<class '__main__.dd'>, <class '__main__.bb'>, <class '__main__.cc'>, , <class 'object'>]
[<class '__main__.cc'>, <class '__main__.aa'>, <class 'object'>]
super函数内有两个参数,第1个参数是类,表示在MRO顺序中,查找这个类的下一个类。上面的代码,如果在bb的__init__中,代码改写成super(cc,self)......就是一个无限递归循环,直到maximum。super函数的那两个参数,可以不写。
以后看到super,就要想到MRO,就搞定了。
MRO满足两个性质:(1)本地优先;(2)单调性;
本地优先:指声明时父类的顺序,比如C(A,B),如果访问C类对象属性时,应该根据声明顺序,优先查找A类,然后再查找B类。
单调性:如果在C的解析顺序中,A排在B的前面,那么在C的所有子类里,也必须满足这个顺序。Python用一个叫C3的算法来生成MRO。
-- EOF --
本文链接:https://www.pynote.net/archives/3500
前一篇:pygame初体验
后一篇:pygame.draw的使用
Ctrl+D 收藏本页
©Copyright 麦新杰 Since 2019 Python笔记