python子类在多继承中使用MRO机制原理

作者:Dante丶 时间:2021-03-09 00:52:35 

子类在多继承中使用MRO机制

在Python中,当定义一个类时,可以指定它的父类。一个子类继承了其所有父类的属性和方法,并且可以添加自己特有的属性和方法。

然而,如果一个类有多个直接父类,那么这些父类之间可能会存在重名的属性和方法。为了正确地调用这些属性和方法,Python使用了一种称为“方法解析顺序”(Method Resolution Order,MRO)的算法来确定属性和方法的查找顺序。

算法原理

在Python 2.x中,MRO采用深度优先搜索算法(DFS)实现。这种算法存在一些问题,导致在某些情况下无法正确解析方法调用顺序。例如:

class A:
   def foo(self):
       print("A.foo")
class B(A):
   pass
class C(A):
   def foo(self):
       print("C.foo")
class D(B, C):
   pass
d = D()
d.foo()  # 输出"A.foo",而不是"C.foo"

在上述代码中,类D继承了类B和类C,并且类C重写了类A的foo()方法。因此,在调用对象d的foo()方法时,理论上应该先调用类C中的foo()方法。然而,由于Python 2.x中采用的是DFS算法,它会先遍历类B,然后再遍历类C,最后才会遍历类A。因此,最终调用的是类A中的foo()方法,而不是类C中的foo()方法。

为了解决这个问题,Python 2.3引入了C3算法,它使用拓扑排序算法来计算MRO列表,从而保证调用方法时的正确性。C3算法的基本原理如下:

  • 新式类(即显式继承object或隐式继承object的类)的MRO列表按照广度优先搜索(BFS)算法进行计算。

  • 对于每个类,其MRO列表应满足以下三个条件:

    • 子类的MRO列表要排在父类的MRO列表前面。

    • 如果两个父类都在一个子类的MRO列表中出现,则它们在该列表中的相对顺序要与它们在该子类的直接父类中出现的相对顺序相同。

    • 一个类不能在其MRO列表中出现两次以上。

这种算法能够正确处理上述示例代码中的情况,从而保证调用方法时的正确性。

查看MRO列表

在Python 3中,可以通过__mro__属性来查看类的MRO列表。例如:

class A:
   def foo(self):
       print("A.foo")
class B(A):
   pass
class C(A):
   def foo(self):
       print("C.foo")
class D(B, C):
   pass
print(D.__mro__)

输出结果为:

(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

其中,<class '__main__.D'>表示类D本身,<class '__main__.B'><class '__main__.C'>分别表示类D的父类B和C,<class '__main__.A'>表示类B和C的共同父类A,<class 'object'>表示所有新式类的基类。这个列表的顺序就是Python运行时查找属性和方法的顺序。

来源:https://juejin.cn/post/7207783106970402877

标签:python,子类,多继承,MRO机制
0
投稿

猜你喜欢

  • python随机模块random使用方法详解

    2022-07-02 04:31:10
  • 定制FileField中的上传文件名称实例

    2022-06-07 14:21:05
  • SQL SERVER 与ACCESS、EXCEL的数据转换

    2024-01-18 04:24:40
  • SQL Server正则表达式 替换函数应用详解

    2023-07-07 23:53:13
  • Python实现注册登录系统

    2021-10-21 20:01:05
  • ODBC的保留字有哪些?

    2009-10-28 18:34:00
  • 使用ERWin进行基于MySQL数据库的物理设计

    2009-01-04 12:54:00
  • ASP怎么读取指定xml 的节点

    2008-04-28 13:12:00
  • Python+OpenCV之图像轮廓详解

    2023-08-10 18:59:42
  • centos7上mysql8.0rpm方式安装教程图解

    2024-01-13 06:23:59
  • Oracle重建控制文件的实例教程

    2024-01-25 11:02:16
  • 教你利用python如何读取txt中的数据

    2023-04-03 14:52:36
  • MySQL系列之六 用户与授权

    2024-01-28 05:37:31
  • fso怎样判断一个盘上是否有文件

    2007-09-26 12:35:00
  • python实现图片上添加图片

    2022-01-13 19:19:05
  • Go语言学习之指针的用法详解

    2024-02-12 06:56:10
  • MYSQL 字符串操作

    2008-11-13 12:34:00
  • 正确理解SQL Server四类数据仓库建模方法

    2008-12-23 15:20:00
  • Flask框架debug与配置项的开启与设置详解

    2022-04-11 17:05:58
  • Python爬虫headers处理及网络超时问题解决方案

    2022-11-19 23:38:34
  • asp之家 网络编程 m.aspxhome.com