这一部分非常重要,我相信很多人心中一直觉得super函数就是调用父类,但是结果是这样吗,我们来好好聊一下这个super。我们先来看一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A:
def __init__(self):
print("A")


class B(A):
def __init__(self):
print("B")

if __name__ == '__main__':
b = B()

# 输出结果:
B

这个是没有问题的,很好理解,我们接着来看下一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
class A:
def __init__(self):
print("A")


class B(A):
def __init__(self):
print("B")
super().__init__()

# 输出结果:
B
A

有人说这不就是调用了父类的方法么,我暂且不说话。并向你扔了2个问题:
1、既然我们重写了B的构造方法,那么为什么还要去调用super?
2、super的执行顺序到底是怎样的?

我们先来看第一个问题:

1
2
3
4
5
6
7
8
9
from threading import Thread


class Mythread(Thread):
def __init__(self, name, user):
self.user = user
# self.name = name
super().__init__(name = name)

这里我们想自己定义一个线程,我们发现在Thread这个函数里面就已经包含了name这个属性:

1
def __init__(self, group=None, target=None, name=None,args=(), kwargs=None, *, daemon=None):

这样我们完全可以使用父类Thread的name属性啊,为啥自己还要定义一个呢?自己定义一个虽说不是不可以,但是我们重点是要了解super的用法。

接下来看第二个问题:

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
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(B, C):
def __init__(self):
print("D")
super(D, self).__init__()


if __name__ == '__main__':
d = D()

假如super方法是调用父类的话,那么输出结果应该是D–>B–>A–>C,真的是这样吗,我们打印一下,结果却是D–>B–>C–>A,所以就不是调用父类的方法了,而是调用的顺序是根据前面的mro算法来的,不信我们可以打印一下:

1
2
3
4
5
print(D.__mro__)

# 输出结果:
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

看到没有,一模一样,所以super调用的不是父类,而是根据mro顺序来进行调用的。