考虑下面的类,其中^ {CD1>}和^ {< CD2>}是父类^ {< CD3>}:
class P1:
def f(self):
print('P1')
class P2:
def f(self):
print('P2')
class C(P1, P2):
def f(self):
print('C')
# super().f()
# super(P1, self).f()
c = C()
c.f()
当我运行它时,它会打印C
如果我取消注释第一行super().f()
,那么它也将打印P1
因为super()
将从直接父级调用该方法,P1
如果我取消第二行的注释,super(P1, self).f()
,那么它也会打印P2
因为super(P1, self)
将从P1
的兄弟P2
调用该方法
我想知道的是,如果有任何方法可以通过调用super()
函数从父类P1
和P2
调用f
方法,而不是像我那样调用两次
或者,有没有其他不使用super
函数的方法
没有什么好方法可以完全满足你的需求。但是,如果您可以同时修改
P1
和P2
,那么您可以实现协作多重继承,您只需要将基类添加到具有该方法的无操作实现的两个父类中:这是因为}(在{}的实例上)中调用{}时,它调用{},因为{}实例的MRO是{}
super
并不完全意味着“我的父类”。它的意思是“此对象的MRO中的下一个”。MRO是方法解析顺序,基本上是在继承中搜索对象的顺序。当在C
中调用super()
时,它会在P1
中找到该方法。但是当在{P2
位于P1
之后,因此它由第二个super
调用拾取需要
GP
类来结束super
调用链。如果没有,最后的super
调用将解析为object
(这是所有继承树的根),并且由于没有这样的方法,您将得到一个错误。基类中的实现不需要做任何事情,它只需要在最后不调用super
Super从派生类的方法解析顺序(MRO)调用下一个方法
方法f的每个实现都应该调用super,父类不需要相互了解,super将自动调用MRO中的下一个方法
编辑:我忘了mro中的最后一个类始终是object。 对象没有名为f的方法。因此,您应该注意,mro中具有该方法的最后一个类要么不调用super().f,要么捕获AttributeError
只要遵循C3线性化规则,子类就可以更改MRO。这意味着派生类决定哪些代码运行,哪些代码不运行。这是依赖性注射的一种方法
您可以通过_MRO__; atribute检查类的MRO
这个答案主要基于雷蒙德·赫廷格的谈话
相关问题 更多 >
编程相关推荐