目录
1. 先说结论
super 函数在继承中的作用:返回 MRO 中的下一个 class 。
2. MRO 和 __mro__ 属性
Method resolution order 简称 MRO,是指 “搜索方法或属性时,对基类的搜索顺序”。 通过一个类的 class.__mro__ 属性,可以查看这个类的 MRO。
从 Python 2.3 开始,就使用 C3 算法得到 MRO。得到的 MRO 顺序有 2 个特点:
- 子类在前,父类在后。
- object class 只出现一次,并且是在整个 MRO 的最后面。
第一个特点在菱形继承时,比较明显。例如一个 class FOO,它继承 2 个父类 A 和 B,并且这两个父类都有共同的父类 ROOT,则 FOO.__mro__ 为: FOO → A → B → ROOT → object
而第二个特点,实际就是第一个特点的应用。因为 object class 是所有 class 的基类,所以 object 也就只能在 MRO 的最后面。
关于 C3 算法可参见官网:https://www.python.org/download/releases/2.3/mro/
3. super 函数
super 函数的作用是:返回 MRO 中的下一个 class 。 可以结合 super 函数的 2 个参数理解:
super(type, object_or_type=None)
- 第二个参数 object_or_type 提供搜索顺序 MRO。使用其 __mro__ 属性即可查看。
- 第一个参数 type 用于确定 MRO 中某个 class,然后会返回下一个 class 。
举例来说:假设 MRO 的结果中,有 A、B 连续两个 class。而 type 参数确定了 A,则 super 会返回下一个 class,即 B ,然后就可以调用 B 的所有方法,如 __init__, __setitem__等。
type 参数的作用是确定 MRO 中某个 class。利用这个 type 参数,就可以跳过一些 class。 下图的例子利用 type 参数,直接跳过了 class B。
4. 多继承
多继承是指有多个基类 base class。
使用多继承时注意一个特点:MRO 中各个 class 都要调用 super 函数,只有最后 2 个 class 不调用 super。
一个多继承的结构如下图。 MRO 为: FOO → A → ROOT → B → object
上图多继承的示例代码如下。
最后 2 个 class 不调用 super,其原因是:
MRO 的最后一个类是 object,它一般没有自定义的方法。而倒数第二个类不使用 super 的原因,也是因为不需要调用下一个类 object class。
Python 的多继承也叫协作式多继承 cooperative multiple inheritance。这里的 cooperative,意思是 MRO 中的各个类必须协作 cooperate,整个继承关系链中的同名方法才能被全部执行。各个类调用 super 函数时,就是在进行协作。
5. 菱形继承
菱形继承是多继承的一个特例,即多个基类共用同一个基类。
一个菱形继承的结构 diamond diagram 如下图,其 MRO 为: FOO → A → B → ROOT
菱形继承的各个 class,同样必须调用 super 函数进行协作,才能保证同名方法能够被执行。
6. 不要直接继承内置的类型 built-in types
不论是单继承还是多继承,都不要使用内置的类型,包括 list, dict 等。
这是因为内置类型通常是用 C 语言写成的,不一定使用覆盖后的方法 overridden methods。直接继承使用时,常常会有很多意外的结果。
如果要继承列表,字典等类,应该用 collections 模块的 UserDict, UserList 和 UserString 等,它们就是专门用来被继承的。
7. 参考资料
- 官网的 super 函数:https://docs.python.org/3/library/functions.html#super
- Raymond Hettinger 的文章 《Python’s super() considered super!》 :https://rhettinger.wordpress.com/2011/05/26/super-considered-super/
- 《Fluent Python》 https://www.oreilly.com/library/view/fluent-python-2nd/9781492056348/