我想创建一个派生自PyQt5 QtWidget.QWidget
和abc.ABCMeta
的类。这两个类都有其自己的元类作为类型,因此,根据this page和this SO question,我需要创建自己的元类,该元类派生自QWidget
和{{1 }},并明确地将其用作我的课程的元类。
到目前为止,我已经定义了一个abc.ABCMeta
类,并将其用作我的QtAbcMeta
类的metaclass
(请参见下文)。
ConcreteWidget
但是,当我尝试调用import abc
from PyQt5 import QtWidgets, QtCore
class AbstractClass(metaclass=abc.ABCMeta):
def __init__(self, name):
self._name = name
@abc.abstractmethod
def myMethod():
pass
class QtAbcMeta(type(QtWidgets.QWidget), type(AbstractClass)):
pass
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.
def myMethod():
print("My widget does something")
def main():
app = QtWidgets.QApplication([])
myWidget = ConcreteWidget('my name', parent=None)
if __name__ == "__main__":
main()
方法的__init__
方法来设置父对象时,会收到以下TypeError:
QtWidgets.QWidget
我不知道这是怎么了。 Traceback (most recent call last):
File "main.py", line 36, in <module>
main()
File "main.py", line 33, in main
myWidget = ConcreteWidget('my name', parent=None)
File "main.py", line 24, in __init__
QtWidgets.QWidget.__init__(self, parent=parent) # This gives a type error.
TypeError: __init__() missing 1 required positional argument: 'name'
的签名是否有所更改?任何帮助将不胜感激。
答案 0 :(得分:1)
根据the docs,您必须将所有参数传递给QWidget,尽管您不需要它:
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
AbstractClass.__init__(self, name)
QtWidgets.QWidget.__init__(self, name=name, parent=parent)
答案 1 :(得分:1)
QT类旨在以协作方式在现代Python代码中使用-这意味着它们在内部使用Python的super()
,以确保使用其各自的参数调用所有超类中的所有适当方法。
super()
的创建完全是为了避免使用超级类名称对超级类__init__
(和其他替代方法)进行硬编码的调用,因此您不必担心呼叫顺序。
唯一的是,每个打算用作多类混合的类都必须“了解”它的状态,提取其使用的命名参数,然后使用其余参数再次调用super
。
QT代码更进一步,并检查是否为其他类提供了所有命名的参数,否则会出错。
更重要的是,由于Qt类本身使用了super,这意味着您在抽象类中的__init__
被调用了两次。在这个简单的代码中不会有什么不同,但是在更复杂的基类中可能是个问题。
因此,只需重写您的__init__
方法即可以“ pythonic”方式进行操作:
class ConcreteWidget(QtWidgets.QWidget, AbstractClass, metaclass=QtAbcMeta):
def __init__(self, name, parent=None):
super().__init__(name=name, parent=parent)