DancedFive 发表于 2023-10-2 16:37:01

[扩展阅读] 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()



这段代码我在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 版本。
如果问题已经解决,请设置最佳答案

Mike_python小 发表于 2023-10-2 16:37:27

这个问题涉及到 Python 中的多继承和方法决议顺序。Python 支持多继承,当一个类有多个父类时,Python 会按照一定的顺序(MRO)来搜索方法。具体来说,对于类 E,它的 MRO 是:


E -> C -> A -> D -> B -> object


也就是说,当通过 e.say() 调用 E 的 say 方法时,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 顺序。另外,在编写代码时,也应该尽量避免使用复杂的多继承结构,以保证代码的可读性和可维护性。

球一个最佳答案谢谢啦!这对我非常重要!{:10_254:}{:10_254:}{:10_254:}

isdkz 发表于 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的顺序正确,并且可以避免继承顺序导致的问题。
页: [1]
查看完整版本: [扩展阅读] super() 中代码运行结果不一致