Python 继承中的方法解析顺序 (MRO)

方法解析顺序 (Method Resolution Order, 简称 MRO) 定义了 Python 在类及其父类中搜索方法的顺序。当一个方法存在于继承链中的多个类里时,尤其是涉及多重继承时,了解这一点就变得至关重要。

让我们看一个例子,看看当父类和子类同时拥有同名方法时,Python 是如何决定执行哪一个的。

class A:
    def fun(self):
        print("In class A")

class B(A):
    def fun(self):
        print("In class B")

a = B()
a.fun()

输出结果

In class B

原理解析:

  • 当调用 obj.fun() 时,Python 首先在类 B 中查找。
  • 由于 B 定义了 fun(),它就会直接运行该方法,而不再去检查类 A。
  • 这里的 MRO 顺序是:B -> A。

多重继承(菱形继承问题)

在多重继承中,一个子类可以继承自多个父类。当这些父类又继承自同一个基类时,这种结构就形成了一个“菱形”,Python 必须决定应该使用哪个类的方法。

class A:
    def fun(self):
        print("In class A")

class B(A):
    def fun(self):
        print("In class B")

class C(A):
    def fun(self):
        print("In class C")

class D(B, C):
    pass

a = D()
a.fun()

输出结果

In class B

原理解析:

  • D 继承自 B 和 C。
  • Python 遵循的 MRO 顺序是:D -> B -> C -> A。
  • 由于 B 中存在 fun(),它被执行,搜索也就停止了。

MRO 中的 C3 线性化算法

Python 使用 C3 线性化算法来决定调用方法时搜索类的顺序。该算法会生成一个单一的、一致的顺序,既尊重继承关系,也尊重父类在代码中的书写顺序。

示例: 这个程序打印了 Python 在方法查找时使用的确切顺序。

class A:
    def fun(self):
        print("In class A")

class B(A):
    def fun(self):
        print("In class B")

class C(A):
    def fun(self):
        print("In class C")

class D(B, C):
    pass

obj = D()
obj.fun()

print(D.__mro__)

输出结果

In class B
(, , , , )

原理解析:

  • 当调用 INLINECODE7487e249 时,Python 遵循 INLINECODE93d84da2 显示的 MRO 顺序。
  • 它会依次检查 D,然后 B,然后 C,最后是 A。
  • 由于 B 定义了 fun(),该方法被执行,搜索停止。

查看类方法解析顺序 (MRO) 的方法

Python 为我们提供了两种方式来检查一个类的方法解析顺序 (MRO):

  • mro 属性: 显示一个元组,包含 Python 搜索方法时所依据的类顺序。
  • mro() 方法: 返回一个包含 MRO 顺序的列表。
class A:
    def fun(self):
        print("In class A")

class B:
    def fun(self):
        print("In class B")

class C(A, B):
    def __init__(self):
        print("Constructor C")

obj = C()

print(C.__mro__) 
print(C.mro())

输出结果

Constructor C
(, , , )
[, , , ]

原理解析:

  • C.__mro__ 以元组的形式返回方法解析顺序。
  • C.mro() 以列表的形式返回相同的顺序。
  • 这个顺序序列表明,当解析任何方法调用时,Python 会先搜索 C,然后是 A,接着是 B,最后是 object

相关文章:

> – Python 中的多重继承

> – Python 多重继承配合 super() 函数的使用

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/48895.html
点赞
0.00 平均评分 (0% 分数) - 0