Welcome

python的super理解

0x01 什么继承

继承(英语:inheritance)是面向对象软件技术当中的一个概念。如果一个类别A“继承自”另一个类别B,就把这个A称为“B的子类别”,而把B称为“A的父类别”也可以称“B是A的超类”。继承可以使得子类别具有父类别的各种属性和方法,而不需要再次编写相同的代码。在令子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能。另外,为子类别追加新的属性和方法也是常见的做法。
— 维基百科

这个概念很好理解,也就是A继承了B,那么A就拥有B的属性和特性,同时A还可以重写和添加自己的新方法和新属性。

0x02 单继承与多继承

这个如果是在单继承的编程语言中差不多这样子就可以结束了,在php中可以这样子写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
class B
{
public function sayHi()
{
echo 'hi';
}
}
class A extends B
{
public function sayHi()
{
parent::sayHi();
echo 'hello';
}
}
$a = A();
$a->sayHi();
// output: hi

但是python是一门多继承的编程语言,当单继承的时候可以这样子写

1
2
3
4
5
6
7
8
9
10
11
class B(object):
def __init__(self):
print('I am B')
class A(B):
def __init__(self):
b = B()
print('I am A')
a = A()

里边用了一个很笨的方法,就是A继承了B了之后,在调用B的方法还是直接实例化了一下,下面用super重写一下

1
2
3
4
5
6
7
8
9
10
11
class B(object):
def __init__(self):
print('I am B')
class A(B):
def __init__(self):
super(A, self).__init__()
print('I am A')
a = A()

用super来替换直接实例化调用的过程,更好的体现了OOP,一般情况下

1
super(cls, instance).method(*args)

会自动把method绑定到instance之前的父类上。

现在开始进入python的多继承的问题,因为python是支持多继承的,如果是python继承了多个class,那么当调用super(cls, instance)的时候调用的是哪个class的方法呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class B(object):
def __init__(self):
print('I am B')
class C(object):
def __init__(self):
print('I am C')
class A(B, C):
def __init__(self):
super(A, self).__init__()
print('I am A')
a = A()
# output:
# I am B
# I am A
#
# 或者
# output
# I am C
# I am B

这里就涉及到了python的方法执行顺序(MRO),在新式类中遵循的是广度优先算法,按照从左往右的顺序,可以通过mro()函数查看一下查找顺序。
而super()已经不是定义为调用当前类父类的方法了,当调用super(A,self).init()调用的是self的mro()执行顺序中A的下一个类中的方法

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
26
27
28
class Root(object):
def __init__(self):
print("this is Root")
class B(Root):
def __init__(self):
print("enter B")
super(B, self).__init__()
print("leave B")
class C(Root):
def __init__(self):
print("enter C")
super(C, self).__init__()
print("leave C")
class D(B, C):
pass
d = D()
# output:
#
# enter B
# enter C
# this is Root
# leave C
# leave B

从上边的例子可以看书super做的工作其实可以看做是

1
2
3
def super(cls, instance):
mro = instance.__class__.mro()
return mro[mor.index(cls) + 1]

super的执行顺序可以看做是这样子,具体的实现还有很多的细节

0x03 写在尾巴

这篇记录的都只适用于新式类,如果不是新式类有很多的不同。