简介Python之super的用法及原理
来源:互联网 发布:90后创业开淘宝店 编辑:程序博客网 时间:2024/05/21 14:40
1. super()的功能
看下面代码:
class B1(object): def __init__(self): self.b1 = 10class B2(object): def __init__(self): self.b2 = 20class S1(B1, B2): def __init__(self): B1.__init__(self) B2.__init__(self) self.s1 = 30if __name__ == "__main__": mys1 = S1() print mys1.b1, mys1.b2, mys1.s1 # 10 20 30
以上是Python2.2之前的写法。
此时,如要将S1的父类B2改成B3,则__init__()中所有和B2相关的都要改成B3的;
并且,由以上也能看出,所有父类的__init__()都要显式地列在S1的__init__()中。
看Python2.2及其之后的写法(Python2.2引入了super())
class B1(object): def __init__(self): super(B1, self).__init__() self.b1 = 10class B2(object): def __init__(self): super(B2, self).__init__() self.b2 = 20class S2(B1, B2): def __init__(self): super(S2, self).__init__() self.s2 = 30if __name__ == "__main__": mys2 = S2() print mys2.b1, mys2.b2, mys2.s2
由以上代码可以看出,如要将S1的父类由B2改成B3,则S2的代码几乎没有什么变动(只有第一行类的定义时,将B2改成B3即可)。
要注意的是,在B1和B2的__init__()函数中都用了super(),那么在S2的__init__()函数中也用super(),则只需写一行super()即可,而不用再显式调用所有父类的__init__()函数了。
2. 注意事项
- 要么采用Python2.2之前的写法,全部显式调用父类的构造器;要么全部用super();不能混用。
- super、MRO都是针对新式类的;如果是传统类,还是采用上面第一段代码中的写法吧。
3. super()的原理
super()其实做的就是这件事:
def super(cls, inst): mro = inst.__class__.mro() return mro[mro.index(cls) + 1]
由以上代码:
1. inst负责生成MRO的list;
2. 定位到当前cls在MRO中的位置,然后后移一位,返回此处的类;
MRO就是Method Resolution Order,详见这篇文章The Python 2.3 Method Resolution Order.
请看下面这个钻石继承的例子:
class A(object): def __init__(self): print "In A's __init__()"class B(A): def __init__(self): print "Enter B's __init__()" super(B, self).__init__() print "Leave B's __init__()"class C(A): def __init__(self): print "Enter C's __init__()" super(C, self).__init__() print "Leave C's __init__()"class D(B, C): passd = D()print d.__class__.__mro__
程序的输出如下:
$ python test_super.pyEnter B's __init__()Enter C's __init__()In A's __init__()Leave C's __init__()Leave B's __init__()(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
从以上程序,可以清楚地看出,在上面这个钻石继承中,最后对于类D来说,其MRO就是 D B C A,故在执行了类B的构造器后,就去执行了类C的构造器,而不是类A的构造器。
关于MRO的一点小总结:
- 基类总是出现在派生类的后面;
- 如果有多个基类,基类的顺序保持不变。
4. 参考文献
- Python的内置函数super()与类方法(函数)继承
- 有关super的问答
- Things to know about Python super
- Python’s super() considered super!
- super on stackoverflow
- The Python 2.3 Method Resolution Order
1 0
- 简介Python之super的用法及原理
- Python中super()函数简介及用法分享
- 【python】super的用法
- 【Python】super的用法
- Python中super的用法
- Python中super的用法
- Python中super的用法
- Python中super的用法
- Python中super的用法
- Python中super的用法
- Python中super的用法
- Python中super的用法
- Python中super的用法
- IntentService用法及原理简介
- Python 中的继承之Super用法
- python之super的问题
- python的super用法遇到的问题
- 关于Python的super()用法的研究
- 函数入栈出栈以及栈帧
- Hibernate 抓取策略
- Mysql主从复制
- Git 执行更改 git commit
- redis教程(三):Redis数据类型及基本的使用
- 简介Python之super的用法及原理
- Java设计模式之封装算法的模板模式
- Git 管理分支
- XX-net部署技巧
- http://www.race604.com/android-context-intro-2/
- 理想就是办一所真正的民办高校
- Qt 自定义PushButton
- 第三周—项目4 顺序表应用
- 【索引】2015 ACM/ICPC Asia Regional Online