python-super1
一、问题的发现与提出
一般子类在继承父类后,若子类覆盖了父类,则只执行子类,不执行父类。如果没有,则执行父类代码。
发现使用super()后,子类,父类都会执行,比较疑惑,记录学习,super知识点
参考网址:https://www.zhihu.com/question/20040039
要谈super,首先应该无视“super"这个名字带给我们的干扰。
不要一说到super 就想到父类!super指的是MRO中的下一个类!
不要一说到super 就想到父类!super指的是MRO中的下一个类!
不要一说到super 就想到父类!super指的是MRO中的下一个类!
MRO全称是Method Resolution Order 代表类继承顺序。
一说到super就想到父类,这是初学者很容易犯的错误,忘了这件事后,在去看这篇文章:python's super() considered super
这是Raymod Hettinger写的一篇文章,对super讲解非常透彻。
简而言之,super其实做的是这件事:
1 def super(cls,inst): 2 mro = inst._class_.mro() 3 return mro[mro.index(cls)+1]
两个参数cls 和 inst 分别做了两件事:
1.inst负责生成MRO的list
2.通过cls定位当前MRO中的index,并返回mro[index+1]
通过这两件事,才是super的实质,一定记住!
举例说明:
输出结果:
1 enter B 2 enter C 3 This is Root 4 leave C 5 leave B 6 (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.Root'>, <type 'object'>)
知道了super和父类其实没有实质联系后,就不难理解为什么“enter B“ 下一句是“enter C“而不是“This is Root“
流程如下:
在B的__init__函数中:super(B,self).__init__()。首先我们获得的是self.__class__.__mro__,注意这里的self是D的instance不是B的。
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.Root'>, <type 'object'>)
然后通过B来定位MRO中的index,并找到下一个。显然B的下一个是C,于是调用C的__init__,打印出“enter C”
为什么B的__init__会被调用:因为D没有定义__init__,所以会在MRO中找下一个类,去查它有没有定义__init__,也就去调用B的__init__。
MRO中类的顺序到底是怎么排的呢,python's super considered super中有解释:
在MRO中,基类(父类)永远在派生类(子类)后面,如果有多个基类(父类),基类的相对顺序保持不变。
无论是super还是MRO都是针对新式类,如果不是新式类,就还是要用父类名调用函数。
其他:
从运行结果看,普通继承和super继承是一样的。但是其实他们的内部运行机制不一样,这一点在多重继承时体现的很明显。在super机制中可以保证公共父类仅被执行依稀,至于执行的顺序,按照mro进行(E._mro_).
注意super继承只能用于新式类,用于经典类时就会报错。
新式类:必须是有继承的类,如果没有什么想继承的,就继承object
经典类:没有父类,如果此时调用super就会出现错误:[super() argument 1 must be type, not classobj]
转载及借鉴:http://www.xker.com/page/e2015/05/191327.html
http://www.cnblogs.com/lovemo1314/archive/2011/05/03/2035005.html
2是1的补充,只不过1比较好看,格式比较简单
posted on 2016-12-06 15:29 zhuzhu2016 阅读(208) 评论(0) 编辑 收藏 举报