Menu
CoddyTech

方法解析顺序

本课属于 Coddy Python 学习旅程的“面向对象编程”单元。第 21 课,共 64 课。

方法解析顺序(MRO)是当多个类具有相同的方法名时,Python 查找方法所使用的顺序。

下面是一个示例,其中多个类具有同一个方法:

class A:
    def method(self):
        return "Method from A"

class B:
    def method(self):
        return "Method from B"

class C(A, B):
    pass

使用 __mro__ 查看 MRO:

print(C.__mro__)

输出:

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

__mro__ 属性是一个元组,包含解析顺序中的所有类。第一个元素(__mro__[0])始终是类本身(C),后面依次是从左到右的父类(A,然后是 B),最后是内置的 object 类。

创建一个对象并调用该方法:

c = C()
print(c.method())

输出:

Method from A

Python 先在类 A 中找到了这个方法(在 MRO 中的索引为 1),所以使用了它。

更改继承顺序,看看有什么不同:

class D(B, A):  # 现在 B 排在 A 前面
    pass

print(D.__mro__)
d = D()
print(d.method())

输出:

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

现在,Python 会先找到 B 的方法,因为在继承列表中,B 排在 A 前面。你可以使用索引访问 MRO 中的特定类:D.__mro__[0] 是 D 本身,D.__mro__[1] 是 B,D.__mro__[2] 是 A。

你也可以使用 mro() 方法:

print(C.mro())

虽然 mro() 和 __mro__ 提供相同的类序列,但它们的类型不同:__mro__ 返回一个 元组,而 mro() 返回一个 列表。

要点:Python 会按 MRO 顺序查找方法,先查类本身(索引 0),再按类定义中从左到右的顺序查找父类(索引 1、2 等)。找到的第一个方法会被使用。

challenge icon

挑战

中等

在这个挑战中,你将实现一个类层次结构。

你需要编辑以下文件:

  • device.py:实现基类 Device
  • screen.py:实现继承自 Device 的 Screen 类
  • computer.py:实现继承自 Device 的 Computer 类
  • laptop.py:实现使用多重继承的 Laptop 类
  • driver.py:实现测试用例,验证你的实现是否正确

每个文件都包含详细的 TODO 注释,会逐步指导你完成实现。

亲手试试

# TODO: 导入所有需要的类
# from device import Device
# from screen import Screen
# from computer import Computer
# from laptop import Laptop

def explain_mro(class_name):
    # TODO: 打印给定类的 MRO(方法解析顺序)
    # TODO: 格式为 "MRO for [class name]:"(注意:冒号后没有空格)
    # TODO: 用 class_name.__name__ 获取类名
    # TODO: 用 class_name.__mro__ 获取 MRO 元组
    # TODO: 将 MRO 中的每个类名分别打印在单独一行
    
    # TODO: 创建该类的一个实例
    # TODO: 在实例上调用 power_on() 并保存结果
    # TODO: 输出:"Power on result: [result]"
    # TODO: 输出一个空行,方便阅读
    pass


# 测试你的代码
# TODO: 分别用 Device、Screen、Computer 和 Laptop 类调用 explain_mro()
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: Python 在线编译器