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 类。