钻石继承课程中调整未绑定父类顺序的困惑
小甲鱼老师在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
烦请大神指点这是为什么?
问题解答:显式调用父类方法与继承顺序的关系
你的困惑源于显式调用父类方法(如 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]