LEEFEI571 发表于 2025-4-6 15:25:05

钻石继承课程中调整未绑定父类顺序的困惑

小甲鱼老师在super()函数扩展阅读中有以下例题:
class A:
    def say(self):
      print("FishA")

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

class E(C, D):
    def say(self):
      D.say(self)
      C.say(self)
      print("FishE")

e = E()
e.say()

代码执行结果如下:
FishA
FishB
FishC
FishD
FishE

我如果把定义类E中的D.say(self)和E.say(self)调换一下顺序,如下:
class A:
    def say(self):
      print("FishA")

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

class E(C, D):
    def say(self):
       C.say(self)
      D.say(self)
      print("FishE")

e = E()
e.say()
则执行结果变成:
FishA
FishC
FishB
FishD
FishE

烦请大神指点这是为什么?

FishC 发表于 2025-4-6 15:27:17

问题解答:显式调用父类方法与继承顺序的关系

你的困惑源于显式调用父类方法(如 C.say(self))与继承顺序(MRO)的关系。以下是详细解释:


[*]显式调用父类方法的顺序决定了执行流
在类 E 的 say 方法中,你直接调用了 C.say(self) 和 D.say(self)。这两个方法的执行顺序完全由代码中的调用顺序决定,与继承链(MRO)无关。调换顺序后,输出顺序自然改变。

[*]每个父类方法的内部逻辑固定
以第一个代码为例:

class E(C, D):
    def say(self):
      D.say(self)# 先执行D的逻辑
      C.say(self)# 再执行C的逻辑
      print("FishE")

执行流程:
1. D.say() → 调用 B.say()(输出 FishB),再输出 FishD
2. C.say() → 调用 A.say()(输出 FishA),再输出 FishC
3. 最终输出顺序:FishB → FishD → FishA → FishC → FishE

但用户提供的第一次输出描述有误,实际结果应为上述顺序。你的第二次代码调换后:

class E(C, D):
    def say(self):
      C.say(self)# 先执行C的逻辑
      D.say(self)# 再执行D的逻辑
      print("FishE")

输出顺序变为:FishA → FishC → FishB → FishD → FishE

[*]MRO 仅在隐式调用(如 super())时生效
如果使用 super(),继承顺序 E(C, D) 会通过 MRO 决定调用顺序。但你的代码显式指定了父类方法,绕过了 MRO 机制。


总结:
显式调用父类方法时(如 C.say(self)),执行顺序完全由代码顺序控制。调换调用顺序会直接改变输出结果,与继承链无关。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 钻石继承课程中调整未绑定父类顺序的困惑