我正在尝试从2个基类继承。
第一个基类(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'
答案 0 :(得分:1)
您在super
上使用了错误的第一个参数:
def __init__(self):
super(Deriv, self).__init__()
super(Base1, self).__init__("Hello world")
但是请注意,这仅是因为Base1.__init__
本身不使用super
,因为这样做的话,它将尝试调用Base2.__init__
,因为这是该方法中的下一个方法。原始对象的MRO。
super
的第一个参数告诉您之后 MRO中的哪个类开始寻找所需的属性。
答案 1 :(得分:1)
您误解了super()
的功能。 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")
如果必须直接处理基类,则不要使用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")