super() 如何能够(显然)解析并调用多个方法?

问题描述 投票:0回答:1

我正在编写一些 Python 代码,看起来它非常适合多重继承,并且我正在阅读有关多重继承的内容,

super()
以确保我正确理解它们的工作原理。

我对

super()
的理解是 - 解释一下 - 它会遍历类的方法解析顺序并返回某种“调度程序”,其中通过
__getattr__
访问方法或属性会访问该方法或属性的“第一个”实现,按照 MRO 的规定。

然而,RealPython 的这个例子让我感到困惑。 (我添加了打印语句,并且编辑了他们的示例以删除所有功能方法,因为我在这里关心的是

super()
如何与 MRO 和各种
__init__
方法一起使用。)

class Rectangle:
    def __init__(self, length, width, **kwargs):
        print("Running Rectangle.__init__")
        self.length = length
        self.width = width
        super().__init__(**kwargs)

class Square(Rectangle):
    def __init__(self, length, **kwargs):
        print("Running Square.__init__")
        super().__init__(length=length, width=length, **kwargs)

class Triangle:
    def __init__(self, base, height, **kwargs):
        print("Running Triangle.__init__")
        self.base = base
        self.height = height
        super().__init__(**kwargs)

class RightPyramid(Square, Triangle):
    def __init__(self, base, slant_height, **kwargs):
        print("Running RightPyramid.__init__")
        self.base = base
        self.slant_height = slant_height
        kwargs["height"] = slant_height
        kwargs["length"] = base
        super().__init__(base=base, **kwargs)

_ = RightPyramid(10, 5)

我的期望是,因为在 RightPyramid 的继承顺序中 Square 位于 Triangle 之前,所以

super(RightPyramid).__init__
相当于
Square.__init__
。确实:

>>> super(RightPyramid).__init__
<bound method Square.__init__ of <__main__.RightPyramid object at [...]>

但是,当我实际运行此代码来查看打印的内容时:

lux@parabolica:~/Desktop $ python test.py
Running RightPyramid.__init__  # No problem
Running Square.__init__  # Square comes first, makes sense
Running Rectangle.__init__  # Square calls Rectangle, gotcha
Running Triangle.__init__  # What? How?!

这是怎么回事?

Triangle.__init__
怎样才能接到电话?

有趣的是,这实际上完全是我希望在我正在处理的代码中发生的事情 - 将来自多个超类的多个

__init__
方法“混合在一起” - 但我没有看到任何文档或文章已阅读表明
super()
应该以这种方式表现。据我所读,
super()
应该只“解析”并调用一个方法;从检查
super(RightPyramid).__init__
来看,似乎这就是正在发生的事情,但从代码的输出来看,
Triangle.__init__
显然被调用了......不知何故。

我在这里误解了什么,在哪里可以阅读有关

super()
的此功能的更多信息?

(这似乎是super()

的官方文档在以“第二个用例是支持协作多重继承......”开头的段落中所指的内容,但它并没有继续说关于这意味着什么、如何工作的任何更具体的信息,或者提供该用例的任何示例。)
    

python multiple-inheritance super method-resolution-order
1个回答
0
投票

super().<method>()

从MRO中的下一个类调用方法,它不会自动调用所有超类中的方法。仅当这些方法中的每一个也调用 
super().<method>()
时,整个 MRO 链才会被处理。

这就是为什么它被称为

合作多重继承——它依赖于每个类通过调用super()

进行合作。

© www.soinside.com 2019 - 2024. All rights reserved.