hbirthday 发表于 5 天前

python理解不了这2个例子的调用顺序

>>> 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。
实在不理解怎么出这个结果的。

FishC 发表于 5 天前

你好!这个问题涉及到 Python 中多继承的 super() 和 MRO(方法解析顺序)机制,确实容易让人困惑。我们来一步步分析。

核心要点:

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


第一个例子分析:

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

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

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

class C(B1, B2):
    def say(self):
      super().say()# 调用 MRO 中下一个类的 say 方法


先查看 C 的 MRO:

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~。

第二个例子分析:

class A:
    def say(self):
      print("FishA")

class B:
    def say(self):
      print("FishB")
      
class C(A):
    def say(self):
      super().say()# 调用 A.say()
      print("FishC")
      
class D(B):
    def say(self):
      super().say()# 调用 B.say()
      print("FishD")

class E(C, D):
    def say(self):
      super().say()# 调用 MRO 中下一个类的 say 方法
      print("FishE")


先查看 E 的 MRO:

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 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: python理解不了这2个例子的调用顺序