简介Python之super的用法及原理
📅 2026/7/17 1:25:33
👁️ 阅读次数
📝 编程学习
1. super()的功能
看下面代码:
classB1(object):def__init__(self):self.b1=10classB2(object):def__init__(self):self.b2=20classS1(B1,B2):def__init__(self):B1.__init__(self)B2.__init__(self)self.s1=30if__name__=="__main__":mys1=S1()printmys1.b1,mys1.b2,mys1.s1# 10 20 30以上是Python2.2之前的写法。
此时,如要将S1的父类B2改成B3,则__init__()中所有和B2相关的都要改成B3的;
并且,由以上也能看出,所有父类的__init__()都要显式地列在S1的__init__()中。
看Python2.2及其之后的写法(Python2.2引入了super())
classB1(object):def__init__(self):super(B1,self).__init__()self.b1=10classB2(object):def__init__(self):super(B2,self).__init__()self.b2=20classS2(B1,B2):def__init__(self):super(S2,self).__init__()self.s2=30if__name__=="__main__":mys2=S2()printmys2.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()其实做的就是这件事:
defsuper(cls,inst):mro=inst.__class__.mro()returnmro[mro.index(cls)+1]由以上代码:
- inst负责生成MRO的list;
- 定位到当前cls在MRO中的位置,然后后移一位,返回此处的类;
MRO就是Method Resolution Order,详见这篇文章The Python 2.3 Method Resolution Order.
请看下面这个钻石继承的例子:
classA(object):def__init__(self):print("In A's __init__()")classB(A):def__init__(self):print("Enter B's __init__()")super(B,self).__init__()print("Leave B's __init__()")classC(A):def__init__(self):print("Enter C's __init__()")super(C,self).__init__()print("Leave C's __init__()")classD(B,C):def__init__(self):print("Enter D's __init__()")super(D,self).__init__()print("Leave D's __init__()")d=D()print(d.__class__.__mro__)程序的输出如下:
Enter D's __init__() Enter B's __init__() Enter C's __init__() In A's __init__() Leave C's __init__() Leave B's __init__() Leave D's __init__() (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class '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
编程学习
技术分享
实战经验