【问题标题】:Multiple Inheritance: missing required positional arguments that aren't actually required多重继承:缺少实际不需要的必需位置参数
【发布时间】:2021-03-30 05:32:09
【问题描述】:

class A:
    def __init__(self, arg):
        print("hit A")
        self.arg = 1
        print("close:A")
        return

class B(A):
    def __init__(self, arg, arg1):
        print("hit B")
        super().__init__(arg)
        self.arg1 = arg1
        print("close B")
        return

class D(A):
    def __init__(self, arg, arg1):
        print("hit D")
        super().__init__(arg)
        self.arg1 = 3
        print("done D")
        return

class C(D, B):
    def __init__(self, arg, arg1):
        print("hit C")
        super().__init__(arg, arg1)
        print("done C")
        return


c = C(1,2)

当 D 调用 A.init 时抛出 TypeError,因为缺少必需的位置参数:arg1。

我知道如何解决这种情况,但我的问题是:为什么会发生这种情况?如果您翻转 D 和 B 的顺序,错误会在 B 中引发,因此无论顺序如何都会发生错误,并且必须与 D 和 B 的编写方式有关,但仅将 arg1 传递给 A 没有意义(尽管它确实解决了它)。我显然不了解 Python 中的 super() 或多重继承。

(顺便说一句,我再也不会这样做了。这是基于一些现实生活中的代码,我使用另一种语言的组合来编写它,并且知道我在这里所做的一切都不是一个好主意。)

【问题讨论】:

    标签: python python-3.x multiple-inheritance


    【解决方案1】:

    当您在 Python 中调用 super 时,该语言使用特定的 Method Resolution Order 来标识要调用的方法。特别是,尽管我们喜欢将继承层次结构可视化为一棵树,但在内部它最终会被线性化,以便 Python 知道调用方法的顺序。具体的线性化过程可以在链接文章中更详细地看到,但在你的如果 MRO 是

    C, D, B, A, object
    

    总结过程(再次,我在这里掩饰了很多),我们从C开始。那是我们名单的首位。然后它的第一个父 D 下一步。然后D 的第一个父母接下来会去。但是D 的第一个父级是A,它也出现在B 的层次结构中,因此为了获得拓扑排序,我们现在需要省略A。然后我们转到B,这是我们列表中的下一个。然后我们继续到B 的父级,即AA 不会出现在我们列表中未包含的任何其他位置,因此我们可以将其包含在内。最后,我们将A 的父级object 包含在内,就完成了。

    所以当你从D 调用super 时,你实际上是在调用B 的初始化器,因为B 在方法解析顺序中是下一个。

    如果这是除初始化程序之外的任何函数其他,则更改参数计数会很糟糕,因为违反了 Liskov 替换。特别是对于初始化程序,我们只需要在使用多重继承时格外小心,以免出现这种特殊情况。

    【讨论】:

      猜你喜欢
      • 2018-09-16
      • 2021-04-07
      • 1970-01-01
      • 2019-12-01
      • 2018-09-09
      • 2014-09-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多