Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何称呼;压倒;来自两个父类的方法?_Python_Python 3.x_Overriding_Multiple Inheritance_Super - Fatal编程技术网

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(自我):