• super深究


    super的入门使用:

    在类的继承中,如果定义某个方法,该方法会覆盖父类的同名方法,但有时候我们希望能同时实现父类的功能,这时,我们就需要调用父类的方法了,可以通过使用super来实现。比如:

    class Animal(object):
        def __init__(self, name):
            self.name = name
    
        def greet(self):
            print(self.name)
    
    
    class Dog(Animal):
        def greet(self):
            super(Dog, self).greet()
            print('wang wang')
    
    obj = Dog('藏獒')
    obj.greet()
    示例

    在上面代码中,Animal是父类,Dog是子类,我们在Dog类定义了greet方法,为了能同时实现父类的功能,我们又调用了父类的方法。
    super的一个最常见用法可以说是在子类中调用父类的初始化方法了。

    深入super:

    以上的使用很简单,无非是获取了父类,并调用父类的方法。其实,在上面的情况下,super获得的类刚好是父类,但在其他情况就不一定了,super其实和父类没有实质性的关联。

    首先看一个复杂点的例子,涉及多继承:

    class Base(object):
        def __init__(self):
            print('enter base')
            print('leave base')
    
    
    class A(Base):
        def __init__(self):
            print('enter A')
            super(A, self).__init__()
            print('leave A')
    
    
    class B(Base):
        def __init__(self):
            print('enter B')
            super(B, self).__init__()
            print('leave B')
    
    
    class C(A, B):
        def __init__(self):
            print('enter C')
            super(C, self).__init__()
            print('leave C')
    
    obj = C()
    示例

    其中,Base是父类,A、B继承Base,C继承A和B,执行结果如下:

    enter C
    enter A
    enter B
    enter base
    leave base
    leave B
    leave A
    leave C

    如果你认为super代表调用父类的方法,那么你很可能疑惑为什么enterA的下一句不是enterBase而是enterB。原因是,super和父类没有实质性的关联,那么super是怎么运作的呢?
    首先看一下MRO表吧:

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

    mro表是通过一个C3线性化算法来实现的,遵循三条原则:

      1、子类永远在父类前面

      2、如果有多个父类,会根据他们在列表中的顺序被检查

      3、如果对下一个类存在两个合法的选择,选择第一个父类

    super原理:

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

    其中,cls代表类,inst代表实例,上面的代码做了两件事:
      1、获取inst的mro列表

      2、查找cls在当前mro列表中的index,并返回它的下一个类,即mro[index+1]

    当你使用super(cls, inst)时,python会在inst的mro列表中搜索下一个类

    现在,再回到上个示例:

    首先看C的__init__方法:

    super(C, self).__init__()
    这里的self是当前实例,即使不创建对象,self也是一个固定的内存地址,这时会打印出enterA,并执行下面一行代码:
    super(A, self).__init__()
    注意:这里的self也是当前C的实例,mro表跟上面是一样的,搜索A在mro列表中的下一个类,发现是B,于是,跳到了B的__init__,这时会打印出enterB,而不是enter base

    整个过程还是比较清晰的,关键是要理解super的工作方式,而不是想当然地认为super调用了父类的方法。

    小结:

    事实上,super和父类没有实质性的关联

    super(cls,inst)获得的是cls在inst的mro列表中的下一个类。

  • 相关阅读:
    animation循环滚动
    <canvas>简单学习
    月末总结
    回顾-总结(2)
    初识正则
    学习中小项目遇到事
    在炎热的夏天学习以提高效率
    前端存储之cookie、localStorage
    总结(1)
    jQuery
  • 原文地址:https://www.cnblogs.com/caibao666/p/6841054.html
Copyright © 2020-2023  润新知