super()干了啥

super()继承

转自:https://www.cnblogs.com/silencestorm/p/8404046.html

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__()  # 等同于python3: super().__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')

C()
print(C.mro())

"""
Enter C
Enter A
Enter B
Enter Base
Leave Base
Leave B
Leave A
Leave C
[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>]
"""

每一个类,都有一个 MRO(Method Resolution Order) 列表。这是python 搜索属性和方法时的顺序。可以通过 class.mro()obj.__class__.mro() 来查看。

>>> A.mro()
[<class '__main__.A'>, <class '__main__.Base'>, <class 'object'>]

super()的原理

def super(class,instance):
    mro = instance.__class__.mro()
    return mro[mro.index(class)+1]  # 返回的是当前 instance 的 mro 列表中的 class索引+1 的类

所以上面代码执行顺序:

line 24: 实例化 C 类
line 21: 执行 C() 实例的 mro 中index=1的类 A
line 9:  此时 super(A, self).__init__() 中的 self,代表的是 C类实例,所以下一步执行 C实例 mro 中的 类B
line 15: 此时的 self 还是 C实例,所以根据mro顺序,下一步执行mro中的 Base类

简而言之,super 可以按照 mro 顺序,找到父类,然后将父类的某个方法,绑定给当前子类的实例,可以让子类调用这个方法:

下面这个例子,子类 B 重写了父类 A 的 abc(),但是我们依然可以调用父类的 abc(),

class A():
    def abc(self):
        # print(self)   # 2. 打印一下 self 这个实例,会发现是类 B 的实例
        return 'abc from A'


class B(A):
    def abc(self):
        print('abc from B')

    def xyz(self):
        x = super(B, self).abc()  # 1. 找到父类的 abc 方法,并使用代理模式,让 self 这个实例可以执行这个方法
        print("x is:", x)
        print('xyz from B')


b = B()
b.xyz()

posted @ 2021-08-09 13:58  wztshine  阅读(68)  评论(0编辑  收藏  举报