python里 super类的工作原理详解
super的工作原理如下:
defsuper(cls,inst): mro=inst.__class__.mro() returnmro[mro.index(cls)+1]
其中,cls代表类,inst代表实例,上面的代码做了两件事:
- 获取inst的MRO列表
- 查找cls在当前MRO列表中的index,并返回它的下一个类,即mro[index+1]
当你使用super(cls,inst)时,Python会在inst的MRO列表上搜索cls的下一个类。
下面看一个例子:
classA:
def__init__(self):
self.n=2
defadd(self,m):
print('\n\nselfis{0}@A.add'.format(self))
self.n+=m
classB(A):
def__init__(self):
self.n=3
defadd(self,m):
print('\n\nselfis{0}@B.add'.format(self))
super(B,self).add(m)
self.n+=3
classC(A):
def__init__(self):
self.n=4
defadd(self,m):
print('\n\nselfis{0}@C.add'.format(self))
super(C,self).add(m)
self.n+=4
classD(B,C):
def__init__(self):
self.n=5
defadd(self,m):
print('\n\nselfis{0}@D.add'.format(self))
print(super(D,self).__self__)
print(super(D,self).__thisclass__)
super(D,self).add(m)
self.n+=5
if__name__=='__main__':
print(D.mro())
d=D()
d.add(2)#等于是:D.add(d,2)
print(d.n)
结果是:
[, , , , ] <__main__.Dobjectat0x101ef16d8> selfis<__main__.Dobjectat0x101ef16d8>@D.add <__main__.Dobjectat0x101ef16d8> selfis<__main__.Dobjectat0x101ef16d8>@B.add selfis<__main__.Dobjectat0x101ef16d8>@C.add selfis<__main__.Dobjectat0x101ef16d8>@A.add 19
来通过这个结果具体说几点细节:
print(D.mro())首先打印出D类的mro列表:[
然后我们通过d=D()创建一个D类的实例:<__main__.Dobjectat0x101ef16d8>;为了方便,我们就把这个实例objectat0x101ef16d8叫做“小明”吧
召唤d.add(2)这个函数的时候,D类中add函数的self实际上就是这个刚被创建的小明同学objectat0x101ef16d8.
那么接下来呢,super(D,self)就是在objectat0x101ef16d8的mro列表中,在小明的MRO列表中,找到classD(D类)的下一个class(类),这里也就是classB(B类)。
注意mro列表里
每一个add函数打印的都是selfis<__main__.Dobjectat0x101ef16d8>,往上追溯的过程中,无论到了哪一级,self始终都是最初创建的那个D类的实例。
这是为什么呢?
注意看print(super(D,self).__self__)那一行返还的输出:<__main__.Dobjectat0x101ef16d8>.
哦哦?!这他妈的不是小明吗?
也就是说,super()虽然找到的是B类,召唤的是B类的add()函数,但它的self仍然是最开始创建的D类实例(我们的小明同学),而且召唤add()这个函数时,仍然是把这样的一个self传给了classB的add()函数。
我们的“小明”,就这样被一次次的往上传导到了每一级的add()函数中,于是每一级打印的都是:
selfis<__main__.Dobjectat0x101ef16d8>或者说:selfis小明
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。