LEEFEI571 发表于 2025-2-23 19:59:49

关于类和对象MRO继承顺序的问题

我在学习小甲鱼老师的在类和对象中讲解MRO顺序的课程对MRO顺序产生了困惑,练习题如下:

>>> class A:
...   def ping(self):
...         print("A ping~")
...
>>> class B(A):
...   def pong(self):
...         print("B pong~")
...
>>> class C(A):
...   def pong(self):
...         print("C pong~")
...
>>> class D(B, C):
...   def pingpong(self):
...         self.ping()
...         self.pong()
...
>>> d = D()
>>> d.pingpong()
>>> # 请问这里会打印什么内容?

答案是:
>>> d.pingpong()
A ping~
B pong~

我的困惑是按照MRO继承顺序,如果相关函数在B类和C类中均出现,那么是否会在B类中先执行,然后再到C类中去执行?还是只在B类中去执行,而不会去C类中再执行?

这道题我的理解是对于ping()方法,由于D类本身中没有,按照MRO继承顺序应该先去B类中找,然而B类中也没有,再去其父类A中去找,此时A类中有ping()方法,故执行相关语句(即打印"A ping~").我的困惑是之后会不会再去类C中找ping方法?我的理解流程如下:

首先是去查找ping()函数
ping()方法查找流程:实例对象d  类D  类B  类A 类C
其次再去找pong()函数
pong()方法查找流程:实例对象d  类D  类B  类A 类C

麻烦大佬帮忙指点一下我的理解是否有误,谢谢!

FishC 发表于 2025-2-23 19:59:58

你对MRO(Method Resolution Order)的理解已经比较准确了。下面是具体的解释。

在 Python 中,当我们调用一个方法时,解释器会根据MRO顺序来查找该方法。MRO是确定类的继承层次和方法解析优先级的规则。MRO的顺序是从当前类开始,按照继承链从左到右依次搜索。

对于你提到的例子:

class A:
    def ping(self):
      print("A ping~")

class B(A):
    def pong(self):
      print("B pong~")

class C(A):
    def pong(self):
      print("C pong~")

class D(B, C):
    def pingpong(self):
      self.ping()
      self.pong()

d = D()
d.pingpong()

这里调用的方法 `pingpong` 会按照以下顺序执行:

1. `self.ping()`
2. `self.pong()`

根据类 `D` 的 MRO 顺序,我们可以通过 `D.__mro__` 来查看:

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

这意味着 `D` 类的MRO顺序是:

1. D
2. B
3. C
4. A
5. object

因此,对于 `self.ping()` 的查找顺序是:
- `D` -> `B` -> `A`

由于 `A` 类中定义了 `ping` 方法,所以会在 `A` 类中找到并执行 `ping` 方法,输出 "A ping~"。

对于 `self.pong()` 的查找顺序是:
- `D` -> `B`

因为 `B` 类中定义了 `pong` 方法,所以会在 `B` 类中找到并执行 `pong` 方法,输出 "B pong~"。

由于 `B` 类中已经有 `pong` 方法,不会再继续查找 `C` 类中的 `pong` 方法。所以答案是:
A ping~
B pong~

你的理解基本正确,只是不需要再去 `C` 类中查找 `ping` 方法了,因为已经在 `A` 类中找到了同名的方法。同理,对于 `pong` 方法,在 `B` 类中找到之后就不会再往下查找。

所以,在 MRO 查找到第一个匹配方法后,就停止继续查找了,不会在其他类中再查找同名方法。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 关于类和对象MRO继承顺序的问题