• python深入理解super


    先抄一下官方的文档:官网文档链接

    class super([type[, object-or-type]])
    返回一个代理对象,它会将方法调用委托给 type 的父类或兄弟类。 这对于访问已在类中被重载的继承方法很有用。

    object-or-type 确定用于搜索的 method resolution order。 搜索会从 type 之后的类开始。

    举例来说,如果 object-or-type 的 mro 为 D -> B -> C -> A -> object 并且 type 的值为 B,则 super() 将会搜索 C -> A -> object。

    object-or-type 的 mro 属性列出了 getattr()super() 所共同使用的方法解析搜索顺序。 该属性是动态的,可以在任何继承层级结构发生更新的时候被改变。

    如果省略第二个参数,则返回的超类对象是未绑定的。 如果第二个参数为一个对象,则 isinstance(obj, type) 必须为真值。 如果第二个参数为一个类型,则 issubclass(type2, type) 必须为真值(这适用于类方法)。

    super 有两个典型用例。 在具有单继承的类层级结构中,super 可用来引用父类而不必显式地指定它们的名称,从而令代码更易维护。 这种用法与其他编程语言中 super 的用法非常相似。

    第二个用例是在动态执行环境中支持协作多重继承。 此用例为 Python 所独有而不存在于静态编码语言或仅支持单继承的语言当中。 这使用实现“菱形图”成为可能,即有多个基类实现相同的方法。 好的设计强制要求这样的方法在每个情况下都具有相同的调用签名(因为调用顺序是在运行时确定的,也因为这个顺序要适应类层级结构的更改,还因为这个顺序可能包括在运行时之前未知的兄弟类)。

    对于以上两个用例,典型的超类调用看起来是这样的:

    class C(B):
        def method(self, arg):
            super().method(arg)    # This does the same thing as:
                                   # super(C, self).method(arg)
    
    • 1
    • 2
    • 3
    • 4

    除了方法查找之外,super() 也可用于属性查找。 一个可能的应用场合是在上级或同级类中调用 描述器。

    请注意 super() 是作为显式加点属性查找的绑定过程的一部分来实现的,例如 super().getitem(name)。 它做到这一点是通过实现自己的 getattribute() 方法,这样就能以可预测的顺序搜索类,并且支持协作多重继承。 对应地,super() 在像 super()[name] 这样使用语句或操作符进行隐式查找时则未被定义。

    还要注意的是,除了零个参数的形式以外,super() 并不限于在方法内部使用。 两个参数的形式明确指定参数并进行相应的引用。 零个参数的形式仅适用于类定义内部,因为编译器需要填入必要的细节以正确地检索到被定义的类,还需要让普通方法访问当前实例。

    ———————————————————————————————————————————————————————
    写一下我的场景和问题:
    我有一个基类,有四个子类继承基类,有一个孙类继承四个子类,原先只有基类有属性,子类只有方法无子类属性,现在给某几个子类增加了属性
    我的需求是:孙类能继承基类、指定子类的属性和方法
    直接上代码吧:

    class A:
        def __init__(self):
            print('Enter A init')
            self.a = 2
            self.b = 'aaa'
    
        def aa(self, m):
            print('self is {0} @A.add'.format(self))
            self.a += m
    
    
    class C(A):
        def __init__(self):
            print('Enter C init')
            super().__init__()
            self.b = 'ccc'
        def cc(self, m):
            print(self.a)
    
    class B(A):
        def __init__(self):
            print('Enter B init')
            super().__init__()
            self.b = 'bbb'
        def bb(self, m):
            print('self is {0} @B.add'.format(self))
            print(self.a)
    
    class D(A):
        def dd(self, m):
            print(self.a)
    
    ————————————————————————————————————————————————————————————————————————————————
    class E(D,C,B):
        def __init__(self):
            super().__init__()
            print('**********')
        def ee(self, m):
            print(self.a)
            print(self.b)
    
        ee = E()  #实例化时,MRO为D→C→B→A
        print(ee.b)  #D无属性,则找C ,找到了
    	运行结果:
    		Enter C init
    		Enter B init
    		Enter A init
    		**********
    		ccc
    ————————————————————————————————————————————————————————————————————————————————
    	#修改为:
    	class E(D,C,B):
    	    def __init__(self):
    	        super(D, self).__init__()
    	        print('**********')
    	    def ee(self, m):
    	        print(self.a)
    	        print(self.b)
        ee = E()  #实例化时,MRO为C→B→A
        print(ee.b)  #D无属性,则找C ,找到了	
    
    运行结果:
    		Enter C init
    		Enter B init
    		Enter A init
    		**********
    		ccc 
         
    ————————————————————————————————————————————————————————————————————————————————
    	#修改为:
    	class E(D,C,B):
    	    def __init__(self):
    	        super(C, self).__init__()
    	        print('**********')
    	    def ee(self, m):
    	        print(self.a)
    	        print(self.b)
        ee = E()  #实例化时,MRO为B→A
        print(ee.b)  #B的b属性为bbb
    	
    运行结果:
    	Enter B init
    	Enter A init
    	**********
    	bbb
    ————————————————————————————————————————————————————————————————————————————————
    	#修改为:
    	class E(D,C,B):
    	    def __init__(self):
    	        super(B, self).__init__()
    	        print('**********')
    	    def ee(self, m):
    	        print(self.a)
    	        print(self.b)
        ee = E()  #实例化时,MRO为A
        print(ee.b)  #A的b属性为aaa
    	
    运行结果:
    Enter A init
    **********
    aaa
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101

    从上面代码可以直观的看出对孙类实例化时执行的过程,就可以控制孙类继承的属性

  • 相关阅读:
    R语言使用epiDisplay包的followup.plot函数可视化多个ID(病例)监测指标的纵向随访图、使用n.of.lines参数指定显示的病例数
    iOS UIDevice设备信息
    QT c++ 堆栈一些理解--限制对象建立在栈上--栈堆区别
    物联网智能油井控制系统
    中国能源统计年鉴面板数据-分省市主要污染物排放指标(包含ECXEL2020年中国统计年鉴)
    Arduino程序设计(三) 光照采集 + 温度采集
    PostgreSQL 长事务导致表膨胀的原因
    Mysql某年根据月份分组统计,没有的为0
    操作系统(1)---操作系统的概念、并发、共享、虚拟、异步、以及操作系统的运行机制及体系结构。
    【PyQt】(自制类)处理鼠标点击逻辑
  • 原文地址:https://blog.csdn.net/DaxiaLeeSuper/article/details/125974124