这似乎是一项如此简单的任务,但我现在花费了太多时间,没有解决方案。这是设置:
class A(object):
def __init__(self, x=0):
print("A.__init__(x=%d)" % x)
class B(object):
def __init__(self, y=1):
print("B.__init__(y=%d)" % y)
class C(A, B):
def __init__(self, x=2, y=3, z=4):
super().__init__(x=x, y=y)
print("C.__init__(z=%d)" % z)
这就是主意,但当然这会导致
TypeError: __init__() got an unexpected keyword argument 'y'
所有其他尝试都以类似方式失败,我可以使用正确的解决方案在互联网上找到 no 资源。唯一的解决方案包括用*args, **kwargs
替换所有init参数。这并不适合我的需要。
根据要求,一个真实世界的例子:
(这使用了一种不同的方法,它具有有效的语法,但会产生不需要的结果。)
from PyQt5.QtCore import QObject
class Settings(object):
def __init__(self, file):
self.file = file
class SettingsObject(object):
def __init__(self, settings=None):
print("Super Init", settings is None)
self.settings = settings
class MyObject(QObject, SettingsObject):
def __init__(self, param):
print("Entering Init")
QObject.__init__(self)
SettingsObject.__init__(self, settings=Settings(__file__))
self.param = param
print("Leaving Init")
结果:
Entering Init
Super Init True
Super Init False
Leaving Init
我希望第Super Init True
行消失。
答案 0 :(得分:3)
似乎有一些你感到困惑的事情,所以:
为什么会得到TypeError: __init__() got an unexpected keyword argument 'y'
?
因为方法解析顺序(MRO)中__init__
的下一个实现是A.__init__
,它只接受x
。 MRO是C
- > A
- > B
,因此您必须A.__init__
接受y
(具体或使用**kwargs
)并将其传递(再次使用super
)至{{1} }。
B.__init__
没有调用每个实现,当然也不能确保它们只获得他们期望的参数,只是调用 next 实施所有参数。
为什么super
会被调用两次,一次使用,一次不使用SettingsObject.__init__
?
settings
似乎包含对QObject.__init__
的调用,super().__init__
调用SettingsObject.__init__
作为MyObject
的MRO中的下一个调用settings
。但是,它不会传递任何settings is None
参数,因此第一次调用它时,您会看到settings
。第二次直接调用它并明确传递settings is not None
,所以你看到SettingsObject
。
您如何撰写混合课程?
我认为这是你应该问的问题。 class SettingsObject: # (object) isn't needed in 3.x
def __init__(self, *args, settings=None, **kwargs):
super().__init__(*args, **kwargs)
self.settings = settings
应该是混合类,因此可以正确设计,以便与其混合的层次结构中的其他类协作。在这种情况下:
QObject.__init__
从你的例子中可以看出MyObject
没有任何必需的参数,但你仍然可以编写混合,以便在可选参数的情况下使用或在其他地方重用。然后class MyObject(SettingsObject, QObject):
def __init__(self, param):
super().__init__(settings=Settings(file))
self.param = param
实现如下:
MyObject
请注意:
SettingsObject
- > QObject
- > super().__init__
;和MyObject
一次,而不是单独调用每个超类实现。作为替代方案,您考虑过构图吗?也许 class MyObject(QObject):
def __init__(self, param, settings=None):
super().__init__()
self.param = param
self.settings = settings
obj = MyObject('something', Settings(__file__))
应该接受设置:
self.settings.method(...)
现在您调用self.method(...)
而不是Installation failed with message Failed to finalize session : Unknown failure (Error: java.lang.SecurityException: Requires android.permission.ASEC_CREATE permission).
,但您没有多重继承引入的复杂性。