一、super() 是什么?
super() 是 Python 提供的内置函数,用于调用父类方法。它常用于类的初始化过程中,尤其在继承链中有多个父类时。
在 Python 中,类的继承是通过“方法解析顺序(MRO)”决定的,super() 会按照这个顺序自动调用合适的父类方法,而不用我们手动指定
二、python里的super().__init__()有什么作用?很多同学没有弄清楚。
super()用来调用父类(基类)的方法,__init__()是类的构造方法,
super().__init__() 就是调用父类的init方法, 同样可以使用super()去调用父类的其他方法。
三、分别理解super()和 __ init __()
1、super()
2、__ init __()
__init__() 是python中的构造函数,在创建对象的时"自动调用"。

定义类时可以不写init方法,系统会默认创建, 你也可以写一个,让你的类在创建时完成一些“动作”。
3、super(). __ init __()
如果子类B和父类A,都写了init方法,
那么A的init方法就会被B覆盖。想调用A的init方法需要用super去调用。
当然,在B内部,除了用super调用父类的方法,也可以用父类名调用,例:
class B(A):
def __init__(self):
A.__init__(self)
print("B init")
关于“覆盖”的疑问?
有人可能会误解“覆盖”的意思,认为“覆盖”了就是没有,为什么还能通过super调用?
覆盖了并不是没有了,A的方法终都还在,但需要在B内部用super调用。
例: A里写了一个方法hi(), B继承自A, B里也写了一个方法hi()。 B的对象在外部调用hi(), 就只能调用B里面写的这个hi()。 想通过B调用A的hi(),只能在B内部用super().hi()调用。
class A:
def hi(self):
print("A hi")
class B(A):
def hello(self):
print("B hello")
b = B()
b.hi() # B里没有写hi(),这里调用的是继承自A的hi()
------------------------------------------------------------------
class A:
def hi(self):
print("A hi")
class B(A):
def hi(self):
print("B hi")
b = B()
b.hi() # 这里调用的就是B自己的hi()
------------------------------------------------------------------
class A:
def hi(self):
print("A hi")
class B(A):
def hi(self):
super().hi() # 通过super调用父类A的hi()
print("B hi")
b = B()
b.hi() # 这里调用的就是B里面的hi()
注意:super() 在 python2、3中的区别
Python3.x 和 Python2.x 的一个区别: Python 3 可以使用直接使用 super().xxx 代替 super(Class, self).xxx :
例:
python3 直接写成 : super().__init__()
python2 必须写成 :super(本类名,self).__init__()
4、关于继承顺序

四、MRO的知识应用
在Python中,MRO(Method Resolution Order)即方法解析顺序,它定义了在多重继承的情况下,Python 解释器查找方法和属性的顺序。在python3中,类采用C3线性化算法来确定MRO。
然后用MRO的概念再来重新理解super().func(),一切就迎刃而解了。严格来说,并不能把类class A1(A):的super().func()单纯理解为执行父类A的func(),而是要理解为执行自己的MRO顺序中的下一个类的func(),而class A1(A)的MRO顺序为:A1->A->object(实例),所以super().func()执行的就是A1的下一个MRO类:A的func()。
class A:
def __init__(self):
print("A init")
class A1(A):
def __init__(self):
super().__init__()
print("A1 init")
class A2(A):
def __init__(self):
super().__init__()
print("A2 init")
class B(A1, A2):
def __init__(self):
super().__init__()
print("B init")
b = B()
print(B.__mro__) # (<class '__main__.B'>, <class '__main__.A1'>, <class '__main__.A2'>, <class '__main__.A'>, <class 'object'>)
MRO顺序为:B->A1->A2->A,所以执行的顺序为:
B.__init__():在B.__init__()内执行了B的super().__init__(),它的含义是执行父类的__init__(),不过这个时候的执行对象是MRO顺序的下一个,即A1,那么进入了A1.__init__()。
A1.__init__():在A1.__init__()内又执行了A1的super().__init__(),这个时候的执行对象是MRO顺序的下一个,即A2,那么又进入了A2.__init__()。
A2.__init__():在A2.__init__()内又执行了A2的super().__init__(),这个时候的执行对象是MRO顺序的下一个,即A,那么又进入了A.__init__()。
A.__init__():在A.__init__()内执行了print("A init"),执行完之后,执行A2的super().__init__()的下一条指令:print("A2 init"),然后执行A1的super().__init__()的下一条指令:print("A1 init"),然后是B的super().__init__()的下一条指令:print("B init")。
所以,最终的输出结果是:
A init
A2 init
A1 init
B init
MRO线性化算法确保了子类不能在其父类之前被搜索,同时父类的顺序决定了它们在MRO中的顺序。了解了这个规律之后,在定义有多个父类的类时,就有了规律可循。
class A:
def __init__(self):
print('A')
class B(A):
def __init__(self):
print('B')
super().__init__()
class C(A):
def __init__(self):
print('C')
super().__init__()
class D(A):
def __init__(self):
print('D')
super().__init__()
class E(B, C):
def __init__(self):
print('E')
super().__init__()
class F(C, D):
def __init__(self):
print('F')
super().__init__()
class G(E, F):
def __init__(self):
print('G')
super().__init__()
看看G的继承顺序

我们发现G继承自E, F是并列的,初始化的时候不会先把E初始化完毕才初始化F。
参考文档:https://blog.csdn.net/a__int__/article/details/104600972

2175

被折叠的 条评论
为什么被折叠?



