gpt4 book ai didi

python - 菱形继承(钻石问题)和 MRO

转载 作者:行者123 更新时间:2023-11-28 17:18:39 26 4
gpt4 key购买 nike

我是 MRO 的新手,在弄清楚这些输出的逻辑时遇到了问题。

情况1:

class A(object):
def save(self):
print "A"

class B(A):
def save(self):
print "B"
super(B, self).save()

class C(A):
def save(self):
print "C"
super(C, self).save()


class D(C, B):
def save(self):
print "D"
super(D,self).save()

D().save()

输出:

D
C
B
A

我的问题是如何 super(C)正在调用 B.save() .

根据 MRO: super(C, self)不是关于“ C 的基类”,而是关于 C 的 MRO 列表中的下一个类.但是没有 BC 的 MRO 列表中.

案例二:
class A(object):
def save(self):
print "A"

class B(A):
def save(self):
print "B"
super(B, self).save()

class C(A):
def save(self):
print "C"
# removed super call here

class D(C, B):
def save(self):
print "D"
super(D,self).save()

D().save()

输出:

D
C

案例3:
class A(object):
def save(self):
print "A"

class B(object):
#inherits object now instead of A
def save(self):
print "B"
super(B, self).save()

class C(A):
def save(self):
print "C"
super(C, self).save()

class D(C, B):
def save(self):
print "D"
super(D,self).save()

D().save()

输出:

D
C
A

问题

如果 B 将如何影响 MRO不是从 A 继承的, 但是 object直接地?

有人可以解释这背后的原因吗?

最佳答案

为了解决这些问题,您首先需要了解维修保养 super () 工作。

维修保养 Python Document - MRO
在 Python 中,MRO 基于 C3 线性化。 (wiki和python文档中有很多例子)

super () (查看 Python 文档 - super())
根据 Python 文档,它说..

Return a proxy object that delegates method calls to a parent or sibling class of type. This is useful for accessing inherited methods that have been overridden in a class. The search order is same as that used by getattr() except that the type itself is skipped.



因此, super () 将根据 进行搜索维修保养 ( classobject.__mro__ ) 它将由父类或同级类满足。

回到你的案例,
案例一 D.__mro__ = (D, C, B, A, object)因此,输出将是 D C B A
案例二
D 的 MRO 与案例 1 中的 D 相同。 ( (D, C, B, A, object) )
但是, super () 将在 停止或满足中号因为 save()在 C 类中没有实现 super 函数调用。

案例3
D 的 MRO 等于 (D, C, A, B, object) .因此,当 super () 达到 A 类中的 save() 函数,它会认为满意。这就是为什么 B 中的保存函数从未被调用过的原因。

此外,如果将 D 的继承顺序从 C, B 切换到 B, C. ( class D(C, B)class D(B, C) )。然后,当您调用 D().save() ,输出将是 数据库 因为 D.__mro__ = (D, B, C, A, object)并且 super() 将在 B 类中得到满足。

此外,据我了解, super () 不是强制子类对象调用 的函数全部 覆盖父类中的函数。如果您想强制您的类调用其父类中的所有覆盖函数。您可以尝试执行以下操作:
class Base(object):
def method(self):
print('Base-method')

class Parent(object):
def method(self):
print('Parent-method')

class Child(Parent):
def method(self):
print('Child-method')
super(Child, self).method()

class GrandChild(Child, Base):
def method(self):
print('GrandChild-method')
for base in GrandChild.__bases__:
base.method(self)
#super(GrandChild, self).method()

然后,当您调用 `GrandChild().method() 时,输出将是:
GrandChild-method
Child-method
Parent-method
Base-method

笔记: GrandChild.__bases__仅包含类 Child 和类 Base

PS。
通过说 满意上面,我的意思是没有更多的 super() 调用。

关于python - 菱形继承(钻石问题)和 MRO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42665175/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com