【问题标题】:What is the Diamond Problem in Python and why its not appear in python2?什么是 Python 中的钻石问题,为什么它没有出现在 python2 中?
【发布时间】:2019-05-29 12:47:49
【问题描述】:

我得到了这个代码:

class A:
 pass

class B(A):
 pass

class C(A):
 pass

class D(A,B):
 pass

d = D()

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

【问题讨论】:

标签: python python-3.x python-2.7 diamond-problem


【解决方案1】:

不是钻石问题!

当两个类有一个共同的祖先,而另一个类将这两个类都作为基类时,就会出现菱形问题,例如:

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 还是来自 @ 的那个是模棱两可的 987654326@.

由于方法解析顺序,Python没有这个问题。简而言之,当您从多个类继承时,如果它们的方法名称冲突,则第一个命名的优先。由于我们指定了D(B, C),所以B.do_thingC.do_thing 之前被调用。

这也是你遇到这个问题的原因。考虑一下:由于 B 在您的示例中继承自 A,因此 B 的方法将位于 A 之前。假设我们有另一个类B_derived,它继承自B。方法解析顺序如下:

B_derived -> B -> A

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

D -> B -> A

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

D -> A -> B -> A

这个,而不是钻石问题,是你得到错误的原因。

(另见this answer)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-14
    • 2021-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多