Python 如何称呼;压倒;来自两个父类的方法?
考虑以下类,其中Python 如何称呼;压倒;来自两个父类的方法?,python,python-3.x,overriding,multiple-inheritance,super,Python,Python 3.x,Overriding,Multiple Inheritance,Super,考虑以下类,其中P1和P2是C的父类: P1类: def f(自我): 打印('P1') P2类: def f(自我): 打印('P2') C类(P1、P2): def f(自我): 打印('C') #super().f() #super(P1,self).f() c=c() c、 f() 当我运行它时,它会打印C 如果我取消注释第一行,super().f(),那么它也将打印P1 因为super()将从直接父级调用该方法,P1 如果我取消第二行的注释,super(P1,self).f(),那么
P1
和P2
是C
的父类:
P1类:
def f(自我):
打印('P1')
P2类:
def f(自我):
打印('P2')
C类(P1、P2):
def f(自我):
打印('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
,则可以实现协作多重继承,您只需将基类添加到具有该方法无操作实现的两个父类:
class GP: # grandparent base class
def f(self):
pass # do nothing
class P1(GP):
def f(self):
print("P1")
super().f()
class P2(GP):
def f(self):
print("P2")
super().f()
class C(P1, P2):
def f(self):
print("C")
super().f()
这是因为super
并不完全意味着“我的父类”。它的意思是“此对象的MRO中的下一个”。MRO是方法解析顺序,基本上是在继承中搜索对象的顺序。当在C
中调用super()
时,它会在P1
中找到方法。但是当在P1
中调用super()
时(在C
的实例上),它调用P2
,因为C
实例的MRO是[C,P1,P2,GP,object]
P2
位于P1
之后,因此它会被第二次超级调用选中
需要使用GP
类来结束super
调用链。如果没有,最后的super
调用将解析为object
(它是所有继承树的根),并且由于没有这样的方法,您将得到一个错误。基类中的实现不需要什么都不做,它只需要在最后不调用super
。没有好的方法可以完全实现您想要的。但是,如果您可以同时修改P1
和P2
,则可以实现协作多重继承,您只需将基类添加到具有该方法无操作实现的两个父类:
class GP: # grandparent base class
def f(self):
pass # do nothing
class P1(GP):
def f(self):
print("P1")
super().f()
class P2(GP):
def f(self):
print("P2")
super().f()
class C(P1, P2):
def f(self):
print("C")
super().f()
这是因为super
并不完全意味着“我的父类”。它的意思是“此对象的MRO中的下一个”。MRO是方法解析顺序,基本上是在继承中搜索对象的顺序。当在C
中调用super()
时,它会在P1
中找到方法。但是当在P1
中调用super()
时(在C
的实例上),它调用P2
,因为C
实例的MRO是[C,P1,P2,GP,object]
P2
位于P1
之后,因此它会被第二次超级调用选中
需要使用GP
类来结束super
调用链。如果没有,最后的super
调用将解析为object
(它是所有继承树的根),并且由于没有这样的方法,您将得到一个错误。基类中的实现不需要做任何事情,它只需要在最后不调用super
。super从派生类的方法解析顺序(MRO)调用下一个方法
方法f的每个实现都应该调用super,父类不需要相互了解,super将自动调用MRO中的下一个方法
编辑:我忘了mro中的最后一个类始终是object。
对象没有名为f的方法。因此,您应该注意,mro中具有该方法的最后一个类要么不调用super().f,要么捕获AttributeError
只要遵循C3线性化规则,子类就可以更改MRO。这意味着派生类决定哪些代码运行,哪些代码不运行。这是依赖性注射的一种方法
您可以通过_MRO__; atribute检查类的MRO
这个答案主要基于雷蒙德·赫廷格的谈话
class P1:
def f(self):
super().f()
print('P1')
class P2:
def f(self):
print('P2')
class C(P1, P2):
def f(self):
super().f()
print('C')
class C2(P2, P1):
def f(self):
super().f()
print('C2')
>>> C().f()
P2
P1
C
>>> C2().f()
P2
C2
>>> C.__mro__
(<class '__main__.C'>, <class '__main__.P1'>, <class '__main__.P2'>, <type 'object'>)
>>> C2.__mro__
(<class '__main__.C2'>, <class '__main__.P2'>, <class '__main__.P1'>, <type 'object'>)
P1类:
def f(自我):
super().f()
打印('P1')
P2类:
def f(自我):
打印('P2')
C类(P1、P2):
def f(自我):
super().f()
打印('C')
C2类(P2、P1类):
def f(自我):
super().f()
打印('C2')
>>>C().f()
P2
P1
C
>>>C2().f()
P2
C2
>>>C._uMRO__
(, , )
>>>C2._uMRO__
(, , )
Super从派生类的方法解析顺序(MRO)调用下一个方法
方法f的每个实现都应该调用super,父类不需要相互了解,super将自动调用MRO中的下一个方法
编辑:我忘了mro中的最后一个类始终是object。
对象没有名为f的方法。因此,您应该注意,mro中具有该方法的最后一个类要么不调用super().f,要么捕获AttributeError
只要遵循C3线性化规则,子类就可以更改MRO。这意味着派生类决定哪些代码运行,哪些代码不运行。这是依赖性注射的一种方法
您可以通过_MRO__; atribute检查类的MRO
这个答案主要基于雷蒙德·赫廷格的谈话
class P1:
def f(self):
super().f()
print('P1')
class P2:
def f(self):
print('P2')
class C(P1, P2):
def f(self):
super().f()
print('C')
class C2(P2, P1):
def f(self):
super().f()
print('C2')
>>> C().f()
P2
P1
C
>>> C2().f()
P2
C2
>>> C.__mro__
(<class '__main__.C'>, <class '__main__.P1'>, <class '__main__.P2'>, <type 'object'>)
>>> C2.__mro__
(<class '__main__.C2'>, <class '__main__.P2'>, <class '__main__.P1'>, <type 'object'>)
P1类:
def f(自我):