IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    python super原理

    wingyiulee发表于 2016-05-22 10:08:59
    love 0

    由于Python是允许多继承的,使用旧的Base.__init__()方式调用基类初始化方法时,在钻石继承的情况下就有可能出现钻石顶的基类函数被调用多次。因此Python2引入了super(A, self).__init__(),等价的python3中则使用super().xx()。虽然super常见于类的__init__中调用父类__init__进行父类相关初始化,但也可以用于调用其他基类函数。super是一个类而不是函数。

    super正确运行依赖于MRO机制。MRO,方法解析顺序,是Python用来确定多继承时方法调用时基类查找顺序的机制。Python使用C3算法把类的关系转化为一个列表。这个类列表的MRO存储__mro__中,通过直接访问__mro__或者mro()可以查看。例如以下钻石继承例子:

    class A(object):
        def __init__(self):
            print('init A')
    
        def show(self):
            print('show A')
    
    class B(A):
        def __init__(self):
            super(B, self).__init__()
            print('init B')
        
        def show(self):
            print('show B')
    
    class C(A):
        def __init__(self):
            super(C, self).__init__()
            print('init C')
    
    
    class D(B, C):
        def __init__(self):
            super(D, self).__init__()
            print('init D')
    

    各类的MRO分别为:

    (<class '__main__.A'>, <type 'object'>)
    (<class '__main__.B'>, <class '__main__.A'>, <type 'object'>)
    (<class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
    (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <type 'object'>)
    

    假设新建D的实例,d = D(),则输出为

    init A
    init C
    init B
    init D
    

    刚好与D的mro列表相反,且A只被调用一次。为什么?

    super(X,self)实际上返回的是self所属类的mro列表中位于当前类X之后的类。逻辑类似以下(super是个类)

    def super(cls, inst):
        mro = inst.__class__.mro()
        return mro[mro.index(cls) + 1]
    

    以super(D, self).__init__()为例,cls为D, inst为self,即d,inst.__class__为D,mro为[D, B, C, A],因此实际执行B.__init__()。
    而B.__init__()执行了super(B, self).__init__(),cls为B, inst为self,即d,inst.__class__为D,mro为[D, B, C, A],因此实际执行C.__init__()。
    最后A.__init__()被执行。

    确切的说super指的不是父类,而是 MRO 中的下一个类!

    MRO的具体计算参考https://www.python.org/download/releases/2.3/mro/或者https://rhettinger.wordpress.com/2011/05/26/super-considered-super/。

    其他:
    https://laike9m.com/blog/li-jie-python-super,70/

    The post python super原理 appeared first on wingyiu.



沪ICP备19023445号-2号
友情链接