我得到了这个代码:
class A: pass class B(A): pass class C(A): pass class D(A,B): pass d = D()
在Python3中,我得到了一个MRO错误。我的意思是,它出现是因为钻石问题。在Python2中,它没有问题。为什么会这样,钻石问题到底是什么?
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_thing在C.do_thing之前被调用。这也是为什么你会遇到这个问题。考虑一下:由于B继承自A,B的方法将在A之前。假设我们有另一个类B_derived,它继承自B。方法解析顺序如下:
d.do_thing()
B
do_thing
C
D(B, C)
B.do_thing
C.do_thing
A
B_derived
B_derived -> B -> A
现在,我们有D代替B_derived,因此我们可以将其替换为:
D
D -> B -> A
然而,请注意,您还指定了D在B之前继承自A,并且根据上面的规则,A也必须在方法解析顺序中位于B之前。这意味着我们得到了一个不一致的链:
D -> A -> B -> A
(See也是这个答案)。
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__
2条答案
按热度按时间lhcgjxsq1#
这不是钻石的问题!
当两个类有一个共同的祖先,而另一个类将这两个类都作为基类时,就会发生菱形问题,例如:
在某些语言中,由于继承的实现方式,当您调用
d.do_thing()
时,您实际上是想要从B
中重写do_thing
,还是从C
中重写do_thing
,这是不明确的。Python没有这个问题,因为 * 方法解析顺序 *。简单地说,当你从多个类继承时,如果它们的方法名冲突,第一个命名的优先。因为我们指定了
D(B, C)
,所以B.do_thing
在C.do_thing
之前被调用。这也是为什么你会遇到这个问题。考虑一下:由于
B
继承自A
,B
的方法将在A
之前。假设我们有另一个类B_derived
,它继承自B
。方法解析顺序如下:现在,我们有
D
代替B_derived
,因此我们可以将其替换为:然而,请注意,您还指定了
D
在B
之前继承自A
,并且根据上面的规则,A
也必须在方法解析顺序中位于B
之前。这意味着我们得到了一个不一致的链:(See也是这个答案)。
hm2xizp92#
钻石问题是多重继承或混合继承中的一个问题,它是指至少有一个父类可以从最底层的类通过多个路径被访问的关系。最底层的类通过不同的路径继承基类的成员,从而产生二义性或产生重复成员。方法解析顺序(MRO)告诉python如何搜索继承的方法。这是在使用super时多重继承或混合继承的情况下出现的()因为MRO告诉你确切的信息,Python将在这里寻找你用super调用的方法()和顺序。每个类都有一个.mro属性,允许我们检查顺序。