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小明
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。