尝试创建同时子类化 PySide6 类的 Python 抽象类时,元类发生冲突

phy*_*ics 7 python pyqt pyside pyside2 pyside6

我正在尝试创建一个抽象基类,它也继承任意 PySide6 类。但是,以下会产生错误TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

from abc import ABC, abstractmethod

from PySide6.QtWidgets import QApplication, QWidget


class MyBaseWidget(QWidget, ABC):

    def __init__(self, parent=None):
        super().__init__(parent=parent)
    
    @abstractmethod
    def foo(self):
        pass


class MyConcreteWidget(MyBaseWidget):

    def __init__(self, parent=None):
        super().__init__(parent=parent)


app = QApplication([])
widget = MyConcreteWidget()
widget.show()
app.exec_()
Run Code Online (Sandbox Code Playgroud)

我尝试使用下面看到的解决方案来解决这个问题(灵感来自解决元类冲突http://www.phyast.pitt.edu/~micheles/python/metatype.html多重继承元类冲突等)。

class MyMeta(ABCMeta, type(QWidget)): pass


class MyBaseWidget(QWidget, metaclass=MyMeta):

    def __init__(self, parent=None):
        super().__init__(parent=parent)
    
    @abstractmethod
    def foo(self):
        pass


class MyConcreteWidget(MyBaseWidget):

    def __init__(self, parent=None):
        super().__init__(parent=parent)


app = QApplication([])
widget = MyConcreteWidget()
widget.show()
app.exec_()
Run Code Online (Sandbox Code Playgroud)

TypeError: Can't instantiate abstract class MyConcreteWidget with abstract methods foo这执行时没有错误,但我预计会出现像实例化时那样的错误MyConcreteWidget。无法强制执行基类的接口确实剥夺了抽象基类的好处。有什么解决办法吗?

A.P*_*osh 4

以下解决方案为我提供了所需的结果。

首先获取您想要扩展的Classes和 他们Metaclasses

from abc import ABC, ABCMeta
from PySide6.QtCore import QObject

QObjectMeta = type(QObject)
Run Code Online (Sandbox Code Playgroud)

CustomMetaClass然后从你想要的Metaclass两个中 选择你的Classes

class _ABCQObjectMeta(QObjectMeta, ABCMeta):...
Run Code Online (Sandbox Code Playgroud)

最后,InterfaceClass通过继承两者Classes并将元类设置为CustomMetaclass

class ABCQObject(QObject, ABC, metaclass=_ABCQObjectMeta):...
Run Code Online (Sandbox Code Playgroud)

此过程可以应用于您想要的任何课程。

最终代码:-

from abc import ABC, ABCMeta

from PySide6.QtCore import QObject
from PySide6.QtWidgets import QWidget

QObjectMeta = type(QObject)
QWidgetMeta = type(QWidget)

class _ABCQObjectMeta(QObjectMeta, ABCMeta):...
class _ABCQWidgetMeta(QObjectMeta, ABCMeta):...


class ABCQObject(QObject, ABC, metaclass=_ABCQObjectMeta):...
class ABCQWidget(QWidget, ABC, metaclass=_ABCQWidgetMeta):...
Run Code Online (Sandbox Code Playgroud)

现在你可以继承这个Abstract类,就像你会做的ABC 那样:-

from abc import abstractmethod
import ABCQWidget


class BaseView(ABCQWidget):

    @abstractmethod
    def setupManager(self, manager):...

    @abstractmethod
    def updateContent(self, content):...
Run Code Online (Sandbox Code Playgroud)