Python 的 super 函数, __mro__ 和多继承

本文详细介绍了Python中的MethodResolutionOrder(MRO)、`__mro__`属性、super函数的作用以及多继承和菱形继承的处理方式。特别强调了避免直接继承内置类型和使用collections模块的用户自定义类的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1. 先说结论

2. MRO 和 __mro__ 属性

3. super 函数

4. 多继承

5. 菱形继承

6. 不要直接继承内置的类型 built-in types

7. 参考资料


1. 先说结论

super 函数在继承中的作用:返回 MRO 中的下一个 class 。

2. MRO 和 __mro__ 属性

Method resolution order 简称 MRO,是指 “搜索方法或属性时,对基类的搜索顺序”。 通过一个类的 class.__mro__ 属性,可以查看这个类的 MRO。

从 Python 2.3 开始,就使用 C3 算法得到 MRO。得到的 MRO 顺序有 2 个特点:

  1. 子类在前,父类在后。
  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(typeobject_or_type=None)

  1. 第二个参数 object_or_type 提供搜索顺序 MRO。使用其 __mro__ 属性即可查看。
  2. 第一个参数 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. 参考资料

  1. 官网的 super 函数:https://docs.python.org/3/library/functions.html#super
  2. Raymond Hettinger 的文章 《Python’s super() considered super!》 :https://rhettinger.wordpress.com/2011/05/26/super-considered-super/ 
  3. 《Fluent Python》 https://www.oreilly.com/library/view/fluent-python-2nd/9781492056348/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值