python super __init__ 理解

代码解析1

先贴代码

代码来源
https://www.runoob.com/python/python-func-super.html
中的笔记

     ---> B ---
A --|          |--> D
     ---> C ---
class A():
    def __init__(self):
        print('enter A')
        print('leave A')


class B(A):
    def __init__(self):
        print('enter B')
        super().__init__()
        print('leave B')


class C(A):
    def __init__(self):
        print('enter C')
        super().__init__()
        print('leave C')


class D(B, C):
    def __init__(self):
        print('enter D')
        super().__init__()
        print('leave D')

d = D()

代码较为简单,D 集成 B 和 C 类 ,B 继承A,C也继承A。
结果

enter D
enter B
enter C
enter A
leave A
leave C
leave B
leave D

python根据MRO顺序进行调用父类的__init__函数,目的是不用重复初始化__init__,

代码解析2

如果不用super会导致重复初始化,


class A():
    def __init__(self):
        self.__a=1
        print('enter A')
        print('leave A')


class B(A):
    def __init__(self):
        self.__a=2
        print('enter B')
        # super().__init__()
        A.__init__(self)
        print('leave B')


class C(A):
    def __init__(self):
        self.__a=3
        print('enter C')
        # super().__init__()
        A.__init__(self)
        print('leave C')


class D(B, C):
    def __init__(self):
        self.__a=4
        print('enter D')
        # super().__init__()
        B.__init__(self)
        C.__init__(self)
        print('leave D')


d = D()
print(d.__class__.__mro__)

代码运行结果为

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

可以看到 A 被多次初始化。

代码解析3

部分类使用super


class A():
    def __init__(self):
        self.__a=1
        print('enter A')
        print('leave A')


class B(A):
    def __init__(self):
        self.__a=2
        print('enter B')
        # super().__init__()
        # A.__init__(self)
        print('leave B')


class C(A):
    def __init__(self):
        self.__a=3
        print('enter C')
        # super().__init__()
        # A.__init__(self)
        print('leave C')


class D(B, C):
    def __init__(self):
        self.__a=4
        print('enter D')
        super().__init__()  ##
        # B.__init__(self) 
        # C.__init__(self)
        print('leave D')


d = D()
print(d.__class__.__mro__)

运行结果

enter D
enter B
leave B
leave D

本来我以为 使用 super().init() 会使父类 B 和C 都初始化 但是 只执行了B 。
因为 super 是根据MRO表进行寻找的,整个过程只是用了一次 super().init() 所以根据MRO表,D的下一个是B 所以只初始化B

代码解析4


class A():
    def __init__(self):
        self.__a=1
        print('enter A')
        print('leave A')


class B(A):
    def __init__(self):
        self.__a=2
        print('enter B')
        super().__init__()   ##
        # A.__init__(self)
        print('leave B')


class C(A):
    def __init__(self):
        self.__a=3
        print('enter C')
        # super().__init__()
        # A.__init__(self)
        print('leave C')


class D(B, C):
    def __init__(self):
        self.__a=4
        print('enter D')
        super().__init__()  ##
        # B.__init__(self)
        # C.__init__(self)
        print('leave D')


d = D()
print(d.__class__.__mro__)

运行结果

enter D
enter B
enter C
leave C
leave B
leave D

我们发现 在 B 类里的super().init() 并没调用 A 的 init 而是调用了C的。

结论

super只根据MRO表调用,下一个类的__init__ 不是 父类
另外,在 D 中执行两次 super().init() 只会初始化两次 B 类。

posted @ 2023-03-28 18:29  雪夜羽  阅读(36)  评论(0编辑  收藏  举报