鱼C论坛

 找回密码
 立即注册
查看: 1969|回复: 3

[已解决][扩展阅读] super() 中代码运行结果不一致

[复制链接]
发表于 2023-10-2 16:37:01 | 显示全部楼层 |阅读模式

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

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

x
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()



这段代码我在VScode上的运行结果是:
FishB
FishD
FishA
FishC
FishE

而小甲鱼给的结果是:
=================== RESTART: C:\Users\goodb\Desktop\FishC.py ===================
FishA
FishB
FishC
FishD
FishE

求大佬指导,是哪里出问题了

原屏幕截图如下:


最佳答案
2023-10-2 16:37:18
根据你提供的信息,问题出在 Python 版本上。从 Python 3.6 开始,类的多重继承顺序不再使用深度优先搜索(DFS)算法,而是使用 C3 线性化算法。

由于 C3 线性化算法和 DFS 算法在多重继承的情况下得到的结果可能不同,所以导致了你所说的运行结果不一致问题。

如果你想要得到和小甲鱼给的结果一样的运行结果,可以将 Python 版本降低到 3.5 及以下版本。或者你也可以学习并理解 C3 线性化算法,从而明白代码中的运行逻辑和继承顺序。

以下是 Python 2.7 版本下的运行结果:
FishA
FishB
FishC
FishD
FishE

请注意,Python 2.7 已经停止维护,建议尽快升级到 Python 3.x 版本。
如果问题已经解决,请设置最佳答案
1696235776284.jpg
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-10-2 16:37:18 | 显示全部楼层    本楼为最佳答案   
根据你提供的信息,问题出在 Python 版本上。从 Python 3.6 开始,类的多重继承顺序不再使用深度优先搜索(DFS)算法,而是使用 C3 线性化算法。

由于 C3 线性化算法和 DFS 算法在多重继承的情况下得到的结果可能不同,所以导致了你所说的运行结果不一致问题。

如果你想要得到和小甲鱼给的结果一样的运行结果,可以将 Python 版本降低到 3.5 及以下版本。或者你也可以学习并理解 C3 线性化算法,从而明白代码中的运行逻辑和继承顺序。

以下是 Python 2.7 版本下的运行结果:
FishA
FishB
FishC
FishD
FishE

请注意,Python 2.7 已经停止维护,建议尽快升级到 Python 3.x 版本。
如果问题已经解决,请设置最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-10-2 16:37:27 | 显示全部楼层
这个问题涉及到 Python 中的多继承和方法决议顺序。Python 支持多继承,当一个类有多个父类时,Python 会按照一定的顺序(MRO)来搜索方法。具体来说,对于类 E,它的 MRO 是:
E -> C -> A -> D -> B -> object
也就是说,当通过 e.say() 调用 Esay 方法时,Python 会按照上述的 MRO 顺序来搜索方法并执行。因此,先执行 D.say,接着执行 C.say,其中 C.say 又会调用 A.say

那么为什么会有不同的结果呢?其实这个问题和 Python 版本有关。在 Python 2.x 中,MRO 确定的原则比较简单:从左往右、深度优先。因此,如果按照左侧的继承顺序来看,应该是先调用 A.say,接着才是 B.say。而在 Python 3.x 中,MRO 确定的原则更加复杂,采用了 C3 线性化算法。这个算法可以保证在多继承情况下,子类的 MRO 能够符合所有父类的 MRO 性质,并且保持之前的继承顺序。因此,在 Python 3.x 中,按照上述的 MRO 顺序来搜索方法才是正确的。

在 VSCode 中执行 Python 代码时,默认使用的是 Python 3.x 版本。而小甲鱼在视频中可能使用的是 Python 2.x 版本,因此会出现不同的结果。

总之,如果你想要在 Python 中使用多继承,并且期望方法的调用顺序与你的预期一致,那么应该注意类的 MRO 顺序。另外,在编写代码时,也应该尽量避免使用复杂的多继承结构,以保证代码的可读性和可维护性。

球一个最佳答案谢谢啦!这对我非常重要!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-10-2 16:37:54 | 显示全部楼层
这段代码中,类E继承了类C和类D,而类C又继承了类A,类D又继承了类B。因此,类E的方法调用顺序应该是D->C->A->B。但是,根据Python的方法解析顺序(MRO),这个顺序可能会因为类的继承顺序而有所不同。

在Python 2中,MRO的计算是使用深度优先搜索算法,而在Python 3中,MRO的计算是使用C3算法。因此,Python 2和Python 3中的MRO计算结果可能会不同。

在这个例子中,你的VScode使用的Python版本可能是Python 3,而小甲鱼使用的Python版本可能是Python 2。因此,两个版本的MRO计算结果不同,导致了输出结果的不同。

如果你想要确保输出结果的一致性,可以使用super()函数来调用父类的方法,而不是直接调用父类的方法。这样可以确保MRO的顺序正确,并且可以避免继承顺序导致的问题。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-12-24 09:51

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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