代码之家  ›  专栏  ›  技术社区  ›  Steve Lorimer

多重继承:第二个基类构造函数要求泄漏到第一个基类构造函数

  •  0
  • Steve Lorimer  · 技术社区  · 6 年前

    第一基类( Base1 )构造函数不接受参数:

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

    Base2 )构造函数接受一个参数, id

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

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

    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'
    

    如何使用正确的参数列表正确调用每个基类构造函数?

    下面是一个示例应用程序,它再现了我遇到的错误:

    #!/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'
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   Martijn Pieters    6 年前

    你误解了什么 super() 超级() __mro__ 类型的方法解析顺序属性(序列) self ,然后找到该序列中第一个参数的位置,然后开始搜索 过去的

    为了你的案子 Deriv.__mro__ 是:

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

    super(Base1, self) __init__ 下一个对象的方法 Base2 super(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")
    

    如果必须直接寻址基类,那么不要使用 超级() ,并直接调用未绑定的方法:

    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")
    
        2
  •  1
  •   chepner    6 年前

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

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

    Base1.__init__ 本身不使用 超级的 ,因为如果它这样做了,它会尝试调用 Base2.__init__ ,因为这是原始对象的MRO中的下一个方法。

    第一个论点 之后