多重继承:second base class constructor requirements leak to first base class constructor

Multiple inheritance: second base class constructor requirements leak to first base class constructor

我正在尝试继承 2 个基 classes.

第一个基础 class (Base1) 构造函数不带参数:

class Base1(object):
    def __init__(self):
        ...

二基class(Base2)构造函数接受一个参数,id:

class Base2(object):
    def __init__(self, id):
        ...

在我的派生 class 中,我尝试依次调用每个基础 class 构造函数:

class Deriv(Base1, Base2):
    def __init__(self):
        super(Base1, self).__init__()
        super(Base2, self).__init__("hello world")

失败并出现以下错误:

    super(Base1, self).__init__()
TypeError: __init__() missing 1 required positional argument: 'id'

如何使用正确的参数列表正确调用每个 base-class 构造函数?

这是一个重现我遇到的错误的示例应用程序:

#!/usr/bin/env python3

class Base1(object):
    def __init__(self):
        pass

class Base2(object):
    def __init__(self, id):
        self.id = id

class Deriv(Base1, Base2):
    def __init__(self):
        super(Base1, self).__init__()
        super(Base2, self).__init__("hello world")

def main():
    Deriv()

if __name__ == '__main__':
    main()

这是回溯:

Traceback (most recent call last):
  File "./test.py", line 20, in <module>
    main()
  File "./test.py", line 17, in main
    Deriv()
  File "./test.py", line 13, in __init__
    super(Base1, self).__init__()
TypeError: __init__() missing 1 required positional argument: 'id'

您对 super 使用了错误的第一个参数:

def __init__(self):
    super(Deriv, self).__init__()
    super(Base1, self).__init__("Hello world")

注意,这只是因为 Base1.__init__ 本身不使用 super,因为如果它使用,它会尝试调用 Base2.__init__,因为那是下一个原始对象的 MRO 中的方法。

super 的第一个参数告诉您 之后 class 在 MRO 中开始寻找所需的属性。

您误解了 super() 的作用。 super()self 的类型中获取 __mro__ 方法解析顺序属性(序列),然后找到该序列中第一个参数的位置,然后开始搜索 past 那一点。

对于你的情况 Deriv.__mro__ 是:

(<class '__main__.Deriv'>, <class '__main__.Base1'>, <class '__main__.Base2'>, <class 'object'>)

super(Base1, self)将开始在下一个对象上搜索__init__方法,这里是Base2super(Base2, self)会找到object。出现错误是因为 Base2.__init__ 必须采用 id 参数,但 super(Base1, self).__init__() 不提供该参数。

您想改用合作继承,并在调用链中传递参数:

class Base1(object):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

class Base2(object):
    def __init__(self, id, *args, **kwargs):
        self.id = id
        super().__init__(*args, **kwargs)

class Deriv(Base1, Base2):
    def __init__(self):
        super().__init__("hello world")

如果必须直接寻址基址 类,则不要使用 super(),而是直接调用未绑定的方法:

class Base1(object):
    def __init__(self):
        pass

class Base2(object):
    def __init__(self, id):
        self.id = id

class Deriv(Base1, Base2):
    def __init__(self):
        Base1.__init__(self)
        Base2.__init__(self, "hello world")