多重继承: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__
方法,这里是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")
我正在尝试继承 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__
方法,这里是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")