[英]python multiple inheritance, calling base class function
I was just trying something with multiple inheritance in python.我只是在尝试在 python 中使用多重继承。 I come up with this我想出了这个
class ParentOne:
def foo(self):
print("ParentOne foo is called")
class ParentTwo:
def foo(self):
print("ParentTwo foo is called")
class Child(ParentOne, ParentTwo):
# how is this working
def call_parent_two_foo(self):
super(ParentOne, self).foo()
# This does not work
def call_parent_foo(self):
super(ParentTwo, self).foo()
def call_super_foo(self):
super(Child, self).foo()
def foo(self):
print("Child foo is called")
if __name__ == "__main__":
child = Child()
child.foo()
child.call_super_foo()
child.call_parent_two_foo()
# child.call_parent_foo() #This gives the below error
# super(ParentTwo, self).foo()
# AttributeError: 'super' object has no attribute 'foo'
and it gives the following output它给出了以下输出
Child foo is called
ParentOne foo is called
ParentTwo foo is called
I am getting confused as to how calling of super(ParentOne, self).foo()
is evaluated in this case.我对在这种情况下如何评估super(ParentOne, self).foo()
调用感到困惑。 As per my understanding ParentOne
class does not have any idea of the methods and attributes of ParentTwo
class.根据我的理解, ParentOne
类对ParentOne
类的方法和属性ParentTwo
。 How does super works in case of multiple inheritance多重继承时super如何工作
Python constructs a method resolution order (MRO) when it builds a class. Python 在构建类时会构造方法解析顺序 (MRO)。 The MRO is always linear. MRO始终是线性的。 If python cannot create a linear MRO, then a ValueError
will be raised.如果 python 无法创建线性 MRO,则会引发ValueError
。 In this case, your MRO probably looks like:在这种情况下,您的 MRO 可能看起来像:
Child -> ParentOne -> ParentTwo -> object
Now when python see's a super(cls, self)
, it basically looks at self
and figures out the MRO.现在,当 python see 是super(cls, self)
,它基本上会查看self
并找出 MRO。 It then uses cls
to determine where we are currently at in the MRO and finally it returns an object which delegates to the next class in the MRO.然后它使用cls
来确定我们当前在 MRO 中的位置,最后它返回一个对象,该对象委托给 MRO 中的下一个类。 So, in this case, a super(Child, self)
call would return an object that delegates to ParentOne
.因此,在这种情况下, super(Child, self)
调用将返回一个委托给ParentOne
的对象。 A super(ParentOne, self)
class would return an object that delegates to ParentTwo
. super(ParentOne, self)
类将返回一个委托给ParentTwo
的对象。 Finally a super(ParentTwo, self)
call would delegate to object
.最后一个super(ParentTwo, self)
调用将委托给object
。 In other words, you can think of super
as a fancier version of the following code:换句话说,您可以将super
视为以下代码的更高级版本:
def kinda_super(cls, self):
mro = inspect.getmro(type(self))
idx = mro.index(cls)
return Delegate(mro[idx + 1]) # for a suitably defined `Delegate`
Note that since super(ParentTwo, self)
returns a "Delegate" to object
, we can see why you're getting an AttributeError
when you try super(ParentTwo, self).foo()
-- Specifically the reason is because object
has no foo
method.请注意,由于super(ParentTwo, self)
向object
返回一个“Delegate”,我们可以看到为什么当您尝试super(ParentTwo, self).foo()
时会收到AttributeError
-- 具体原因是因为object
没有foo
方法。
You may understand Child(ParentOne, ParentTwo)
as two separate inheritances within a chain: Child(ParentOne(ParentTwo))
.您可以将Child(ParentOne, ParentTwo)
理解为链中的两个独立继承: Child(ParentOne(ParentTwo))
。 Actually, ParentOne
doesn't inherit ParentTwo
, they are two separate classes, but the method super
works like there's a chain of inheritances (in case of multiple inheritance only).实际上, ParentOne
不继承ParentTwo
,它们是两个独立的类,但是super
方法的工作原理就像有一个继承链(仅在多重继承的情况下)。 I like this example to understand better what's going on (for Python 3.x):我喜欢这个例子来更好地理解发生了什么(对于 Python 3.x):
class P:
def m(self):
print("P")
class A(P):
def m(self):
super().m() # -> B, if we inherit like C(A, B)
print("A")
class B(P):
def m(self):
super().m() # -> P, if we inherit like C(A, B)
print("B")
class C(A, B):
def m(self):
super().m() # -> A
print("C")
A.m(self)
B.m(self)
c = C()
c.m()
It also considers a case if two parents inherit one base class.它还考虑了两个父级继承一个基类的情况。 The script above prints:上面的脚本打印:
P
B
A
C
P
B
A
P
B
class X1:
def run(self):
print("x1")
class X2:
def run(self):
print("x2")
class X3:
def run(self):
print("x3")
class X2:
def run(self):
print("x2")
class Y(X1, X2, X3):
def run(self):
print("y")
Given an instance:给定一个实例:
y = Y()
To call base class function:调用基类函数:
super(Y,y).run()
super(X1,y).run()
super(X2,y).run()
y.run()
Output输出
x1
x2
x3
y
Similarity,相似,
super(Y, y).run()
for cls in y.__class__.__bases__:
if(cls != X3):
super(cls,y).run()
y.run()
Output输出
x1
x2
x3
y
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.