在多级和多级继承中使用 super()
Posted
技术标签:
【中文标题】在多级和多级继承中使用 super()【英文标题】:Usage of super() in Multiple and Multilevel inheritance 【发布时间】:2020-07-04 16:15:18 【问题描述】:我是多级和多级继承的新手。我试图执行一个例子:
class First(object):
def __init__(self):
super().__init__()
print("first")
class Second(object):
def __init__(self):
super().__init__()
print("second")
class Third(First, Second):
def __init__(self):
super().__init__()
print("third")
Third()
我得到的输出是:
second
first
third
<__main__.Third at 0x21bbaf2fc88>
谁能解释一下这个输出的原因? 我期望输出是:
first
second
third
因为第三类的 __init__() 会调用第一类的 __init__()(因为它在父列表中是第一个),它会首先打印第二类的 __init__(),最后是第三类的 __init__()。
MRO 打印出我预期的结果。
print(Third.__mro__)
打印
(__main__.Third, __main__.First, __main__.Second, object)
【问题讨论】:
【参考方案1】:如果你调用super().__init__()
之前你调用print(xxx)
,显示的顺序是正确的。
如果您希望订单显示在“例外”选项卡中,您可以将每个print(xxx)
替换为super().__init__()
,这样就可以解决问题。
代码:
class First(object):
def __init__(self):
print("first")
super().__init__()
class Second(object):
def __init__(self):
print("second")
super().__init__()
class Third(First, Second):
def __init__(self):
print("third")
super().__init__()
Third()
【讨论】:
如果我在 super 之后有打印,你如何证明订单的合理性。在第一类和第二类的情况下,super().__init__()
没有做任何事情
第一个答案:这与在递归中调整打印顺序相同。第二个答案:super()
并不意味着你的父类,它意味着 MRO 列表中的下一个,这就是为什么 First
中的 super()
调用 Second.__init__
而不是 object.__init__
【参考方案2】:
这似乎只是您在__init__
中打印时的产物。您当前的代码在调用super().__init__
之后打印,因此继承层次结构以相反的顺序打印出来。如果您在超级调用之前打印,它将与 MRO 的顺序相同。如果你用两种方式打印,也许最容易理解:
class First(object):
def __init__(self):
print("first (top)")
super().__init__()
print("first (bottom)")
class Second(object):
def __init__(self):
print("second (top)")
super().__init__()
print("second (bottom)")
class Third(First, Second):
def __init__(self):
print("third (top)")
super().__init__()
print("third (bottom)")
现在Third()
的输出应该是:
third (top)
first (top)
second (top)
second (bottom)
first (bottom)
third (bottom)
您看到的输出<__main__.Third ...>
不是由您的任何代码打印的,而是由交互式shell 打印的。这是调用类的实例Third
的结果。如果您执行instance = Third()
,您将看不到这一点,因为该值将存储到变量中,而不是打印出来。 REPL(Read Eval Print Loop)仅在 Python 以交互方式运行时运行,它不会在您导入或作为脚本运行的模块中进行任何额外的打印。
【讨论】:
不应该先(下)在第一个(上)之后打印。神器是什么意思? 不,所有的调用都是嵌套的。Third.__init__
调用First.__init__
,它调用Second.__init__
(它调用object.__init__
,它什么都不做)。 super()
表示“MRO 的下一个”,而不是“我所有的父类”。这就是为什么你会得到First
->Second
调用,而不是First
调用object
的原因,就像它对不同实例所做的那样。
Third.__init__
调用 First.__init__
调用 object.__init__
什么都不做。 First.__init__
不像你提到的那样调用 Second.__init__
。
不,我猜对了。这就是为什么您按照我显示的顺序获得打印输出的原因(我通过运行代码对其进行了测试,这不仅仅是理论)。 Python 的super
真的是超级。它在多重继承的情况下做了一些特殊的事情,这样两个互不了解的基类仍然可以协作。在这种情况下,它是First.__init__
调用super().__init__()
,对于Third
实例,这意味着接下来调用Second.__init__
。这很奇怪,但很有用!如果您直接创建了First
实例,它不会那样做,正如您所说,它会直接跳转到object.__init__
。以上是关于在多级和多级继承中使用 super()的主要内容,如果未能解决你的问题,请参考以下文章