什么是Python中的钻石问题,为什么它没有出现在python2中?

cnh2zyt3  于 2023-04-22  发布在  Python
关注(0)|答案(2)|浏览(131)

我得到了这个代码:

class A:
 pass

class B(A):
 pass

class C(A):
 pass

class D(A,B):
 pass

d = D()

在Python3中,我得到了一个MRO错误。我的意思是,它出现是因为钻石问题。在Python2中,它没有问题。为什么会这样,钻石问题到底是什么?

lhcgjxsq

lhcgjxsq1#

这不是钻石的问题!
当两个类有一个共同的祖先,而另一个类将这两个类都作为基类时,就会发生菱形问题,例如:

class A:
    def do_thing(self):
        print('From A')

class B(A):
    def do_thing(self):
        print('From B')

class C(A):
    def do_thing(self):
        print('From C')

class D(B, C):
    pass

d = D()
d.do_thing()

在某些语言中,由于继承的实现方式,当您调用d.do_thing()时,您实际上是想要从B中重写do_thing,还是从C中重写do_thing,这是不明确的。
Python没有这个问题,因为 * 方法解析顺序 *。简单地说,当你从多个类继承时,如果它们的方法名冲突,第一个命名的优先。因为我们指定了D(B, C),所以B.do_thingC.do_thing之前被调用。
这也是为什么你会遇到这个问题。考虑一下:由于B继承自AB的方法将在A之前。假设我们有另一个类B_derived,它继承自B。方法解析顺序如下:

B_derived -> B -> A

现在,我们有D代替B_derived,因此我们可以将其替换为:

D -> B -> A

然而,请注意,您还指定了DB之前继承自A,并且根据上面的规则,A也必须在方法解析顺序中位于B之前。这意味着我们得到了一个不一致的链:

D -> A -> B -> A
  • 这个 *,而不是钻石问题,就是为什么你得到一个错误。

(See也是这个答案)。

hm2xizp9

hm2xizp92#

钻石问题是多重继承或混合继承中的一个问题,它是指至少有一个父类可以从最底层的类通过多个路径被访问的关系。最底层的类通过不同的路径继承基类的成员,从而产生二义性或产生重复成员。方法解析顺序(MRO)告诉python如何搜索继承的方法。这是在使用super时多重继承或混合继承的情况下出现的()因为MRO告诉你确切的信息,Python将在这里寻找你用super调用的方法()和顺序。每个类都有一个.mro属性,允许我们检查顺序。

class vehicle(object):
     def __init__(self,name):
         print(name,"is vehicle")
class fly(vehicle):
     def __init__(self,canfly):
         print(canfly,"can fly")
         super().__init__(canfly)
class run(vehicle):
     def __init__(self,canrun):
         print(canrun,"can run")
         super().__init__(canrun)
class both(run,fly):
     def __init__(self,name):
         super().__init__(name)
vehicle=both("mig")
both.__mro__

相关问题