深入理解Python 关于supper 的 用法和原理
一、前言
Python面向对象中有继承这个概念,初学时感觉很牛逼,里面也有个super类,经常见到,最近做一些题才算是理解了。特地记录分享给后来研究的小伙伴,毕竟现在小学生都开始学了(滑稽脸)
二、代码
直接上干货,能把下面一个问题全答对,后面就不用看了。
classA(): defgo(self): print("goAgo!") defstop(self): print("stopAstop!") defpause(self): raiseException("NotImplemented") classB(A): defgo(self): super(B,self).go() print("goBgo!") classC(A): defgo(self): super(C,self).go() print("goCgo!") defstop(self): super(C,self).stop() print("stopCstop!") classD(B,C): defgo(self): super(D,self).go() print("goDgo!") defstop(self): super(D,self).stop() print("stopDstop!") defpause(self): print("waitDwait!") classE(B,C): pass a=A() b=B() c=C() d=D() e=E() #说明下列代码的输出结果 a.go() print('--------') b.go() print('--------') c.go() print('--------') d.go() print('--------') e.go() print('--------') a.stop() print('--------') b.stop() print('--------') c.stop() print('--------') d.stop() print('--------') e.stop() print(D.mro()) a.pause() b.pause() c.pause() d.pause() e.pause()
当然,直接运行就有答案了,还是要仔细想一下,反正看到我第一次跑出的结果的时候,我都不敢相信自己的眼睛。
step1:
几个概念:
继承的功能:父类的代码重用
多态的功能:同一方法对不同类型的对象会有相应的结果
开闭原则:对扩展开放,对修改封闭
super类功能:新式类实现广度优先的不重复的调用父类,解决了钻石继承(多继承)的难题
step2:
super实现原理:通过c3算法,生成mro(methodresolutionorder)列表,根据列表中元素顺序查询调用
新式类调用顺序为广度优先,旧式类为深度优先
step3:
个人理解:
1.调用了父类的方法,出入的是子类的实例对象
2.新式类子类(A,B),A就在B之前
3.super类似于嵌套的一种设计,当代码执行到super实例化后,先去找同级父类,若没有其余父类,再执行自身父类,再往下走,
简洁点的三个原则就是:
子类在父类前,所有类不重复调用,从左到右
理解了以上的说法,题目就没问题了。
也不用跑了,答案如下:
a.go()#goAgo! b.go()#goAgo!#goBgo! c.go()#goAgo!#goCgo! d.go()#goAgo!#goCgo!#goBgo!#goDgo! e.go()#goAgo!#goCgo!#goBgo! a.stop()#stopAstop! b.stop()#stopAstop! c.stop()#stopAstop!#stopCstop! d.stop()#stopAstop!#stopCstop!#stopDstop! e.stop()#stopAstop! a.pause()#...Exception:NotImplemented b.pause()#...Exception:NotImplemented c.pause()#...Exception:NotImplemented d.pause()#waitDwait! e.pause()#...Exception:NotImplemented
看了答案,其实还有一点,父类抛异常的情况,如果子类有不抛异常的方法,异常就不抛出了,这个设计也会很有用。
这里就中间一个A,C,B,D的和网上常见的不太一样,促使我仔细研究了一下,其实就是个人理解第三条。
补充:
Python2和Python3在这个问题上的差别
Python2没有默认继承object
Python3默认全部继承object类,都是新式类
Python2super调用super(开始类名,self).函数名()
Python3 super().函数名()
关于调用父类函数传入子类实例的栗子举一个:
classA: def__init__(self): self.n=2 defadd(self,m): print('selfis{0}@A.add'.format(self)) self.n+=m classB(A): def__init__(self): self.n=3 defadd(self,m): print('selfis{0}@B.add'.format(self)) super().add(m) print('newb') self.n+=3 classC(A): def__init__(self): self.n=4 defadd(self,m): print('selfis{0}@C.add'.format(self)) super().add(m) print('newc') self.n+=4 classD(B,C): def__init__(self): self.n=5 defadd(self,m): print('selfis{0}@D.add'.format(self)) super().add(m) self.n+=5 d=D() d.add(2) print(d.n)
总结
以上所述是小编给大家介绍的Python关于supper的用法和原理,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!