鱼C论坛

 找回密码
 立即注册
查看: 32|回复: 1

[已解决]python理解不了这2个例子的调用顺序

[复制链接]
发表于 昨天 17:03 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
>>> class A:
...     def say_hi(self):
...         print("Hi from A~")
...
...     def say(self):
...         super().say_hi()
...
>>> class B1(A):
...     def say_hi(self):
...         print("Hi from B1~")
...
...     def say(self):
...         super().say()
...
>>> class B2:
...     def say_hi(self):
...         print("Hi from B2~")
...   
...     def say(self):
...         super().say()
...
>>> class C(B1, B2):
...     def say(self):
...         super().say()
...
>>> c = C()
>>> c.say()
# 请问这里会打印什么内容?
>>> c = C()
>>> c.say()
Hi from B2~

不能理解,为什么只显示了Hi from B2~。
我的理解,应该是先调用B1,B1得去调用A,然后就调出了Hi from A~,应该没有B2什么事才对呀??

>>> class A:
...     def say(self):
...         print("FishA")
...
>>> class B:
...     def say(self):
...         print("FishB")
...         
>>> class C(A):
...     def say(self):
...         super().say()
...         print("FishC")
...         
>>> class D(B):
...     def say(self):
...         super().say()
...         print("FishD")
...
>>> class E(C, D):
...     def say(self):
...         super().say()
...         print("FishE")
...
>>> e = E()
>>> e.say()
# 请问这里会打印什么内容?
>>> e = E()
>>> e.say()
FishA
FishC
FishE

这个例子,按我的理解,应该是先打印C,C从A调用,所以调出FishA,然后调用完C后就调用D,D要从父类B调用,所以调用出FishB。
实在不理解怎么出这个结果的。
最佳答案
昨天 17:04
你好!这个问题涉及到 Python 中多继承的 super() 和 MRO(方法解析顺序)机制,确实容易让人困惑。我们来一步步分析。

核心要点:
  • super() 并不是直接调用“父类”的方法,而是按照 MRO 顺序调用“下一个”类的方法。
  • MRO 顺序可以通过 类名.__mro__ 查看。


第一个例子分析:

  1. class A:
  2.     def say_hi(self):
  3.         print("Hi from A~")
  4.     def say(self):
  5.         super().say_hi()  # 注意:这里调用的是 say_hi,不是 say

  6. class B1(A):
  7.     def say_hi(self):
  8.         print("Hi from B1~")
  9.     def say(self):
  10.         super().say()  # 调用 MRO 中下一个类的 say 方法

  11. class B2:
  12.     def say_hi(self):
  13.         print("Hi from B2~")
  14.     def say(self):
  15.         super().say()  # 如果找不到,最终会调用 object 的方法(可能出错)

  16. class C(B1, B2):
  17.     def say(self):
  18.         super().say()  # 调用 MRO 中下一个类的 say 方法
复制代码


先查看 C 的 MRO:

  1. print(C.__mro__)
复制代码

输出: (<class '__main__.C'>, <class '__main__.B1'>, <class '__main__.A'>, <class '__main__.B2'>, <class 'object'>)

调用 c.say() 的完整流程:
  • C.say() 中的 super().say() 根据 MRO 找到下一个类 B1
  • B1.say() 中的 super().say() 找到下一个类 A
  • A.say() 中的 super().say_hi() 找到下一个类 B2(因为 MRO 中 A 之后是 B2)。
  • B2.say_hi() 被调用,打印 Hi from B2~

因此,最终只打印了 Hi from B2~

第二个例子分析:

  1. class A:
  2.     def say(self):
  3.         print("FishA")

  4. class B:
  5.     def say(self):
  6.         print("FishB")
  7.         
  8. class C(A):
  9.     def say(self):
  10.         super().say()  # 调用 A.say()
  11.         print("FishC")
  12.         
  13. class D(B):
  14.     def say(self):
  15.         super().say()  # 调用 B.say()
  16.         print("FishD")

  17. class E(C, D):
  18.     def say(self):
  19.         super().say()  # 调用 MRO 中下一个类的 say 方法
  20.         print("FishE")
复制代码


先查看 E 的 MRO:

  1. print(E.__mro__)
复制代码

输出: (<class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.D'>, <class '__main__.B'>, <class 'object'>)

调用 e.say() 的完整流程:
  • E.say() 中的 super().say() 根据 MRO 找到下一个类 C
  • C.say() 中的 super().say() 找到下一个类 A
  • A.say() 被调用,打印 FishA,然后返回。
  • C.say() 继续执行,打印 FishC,然后返回。
  • E.say() 继续执行,打印 FishE

注意:由于 A.say() 中没有调用 super(),所以调用链在此终止,不会继续调用 D 或 B 的方法。因此最终输出三行。

总结:
  • MRO 顺序决定了 super() 的查找路径。
  • 调用链会在某个方法中没有 super() 时终止。
  • 建议在实际代码中,如果设计多继承,确保每个类中的相关方法都通过 super() 正确协作。


希望这个解释能帮助你理解!如果还有疑问,欢迎继续讨论。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 昨天 17:04 | 显示全部楼层    本楼为最佳答案   
你好!这个问题涉及到 Python 中多继承的 super() 和 MRO(方法解析顺序)机制,确实容易让人困惑。我们来一步步分析。

核心要点:
  • super() 并不是直接调用“父类”的方法,而是按照 MRO 顺序调用“下一个”类的方法。
  • MRO 顺序可以通过 类名.__mro__ 查看。


第一个例子分析:

  1. class A:
  2.     def say_hi(self):
  3.         print("Hi from A~")
  4.     def say(self):
  5.         super().say_hi()  # 注意:这里调用的是 say_hi,不是 say

  6. class B1(A):
  7.     def say_hi(self):
  8.         print("Hi from B1~")
  9.     def say(self):
  10.         super().say()  # 调用 MRO 中下一个类的 say 方法

  11. class B2:
  12.     def say_hi(self):
  13.         print("Hi from B2~")
  14.     def say(self):
  15.         super().say()  # 如果找不到,最终会调用 object 的方法(可能出错)

  16. class C(B1, B2):
  17.     def say(self):
  18.         super().say()  # 调用 MRO 中下一个类的 say 方法
复制代码


先查看 C 的 MRO:

  1. print(C.__mro__)
复制代码

输出: (<class '__main__.C'>, <class '__main__.B1'>, <class '__main__.A'>, <class '__main__.B2'>, <class 'object'>)

调用 c.say() 的完整流程:
  • C.say() 中的 super().say() 根据 MRO 找到下一个类 B1
  • B1.say() 中的 super().say() 找到下一个类 A
  • A.say() 中的 super().say_hi() 找到下一个类 B2(因为 MRO 中 A 之后是 B2)。
  • B2.say_hi() 被调用,打印 Hi from B2~

因此,最终只打印了 Hi from B2~

第二个例子分析:

  1. class A:
  2.     def say(self):
  3.         print("FishA")

  4. class B:
  5.     def say(self):
  6.         print("FishB")
  7.         
  8. class C(A):
  9.     def say(self):
  10.         super().say()  # 调用 A.say()
  11.         print("FishC")
  12.         
  13. class D(B):
  14.     def say(self):
  15.         super().say()  # 调用 B.say()
  16.         print("FishD")

  17. class E(C, D):
  18.     def say(self):
  19.         super().say()  # 调用 MRO 中下一个类的 say 方法
  20.         print("FishE")
复制代码


先查看 E 的 MRO:

  1. print(E.__mro__)
复制代码

输出: (<class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class '__main__.D'>, <class '__main__.B'>, <class 'object'>)

调用 e.say() 的完整流程:
  • E.say() 中的 super().say() 根据 MRO 找到下一个类 C
  • C.say() 中的 super().say() 找到下一个类 A
  • A.say() 被调用,打印 FishA,然后返回。
  • C.say() 继续执行,打印 FishC,然后返回。
  • E.say() 继续执行,打印 FishE

注意:由于 A.say() 中没有调用 super(),所以调用链在此终止,不会继续调用 D 或 B 的方法。因此最终输出三行。

总结:
  • MRO 顺序决定了 super() 的查找路径。
  • 调用链会在某个方法中没有 super() 时终止。
  • 建议在实际代码中,如果设计多继承,确保每个类中的相关方法都通过 super() 正确协作。


希望这个解释能帮助你理解!如果还有疑问,欢迎继续讨论。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-12-19 05:02

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表