gpt4 book ai didi

python - 三重继承导致元类冲突......有时

转载 作者:IT老高 更新时间:2023-10-28 21:40:30 25 4
gpt4 key购买 nike

看起来我偶然发现了一个元类 hell ,即使我不想与它有任何关系。

我正在使用 PySide 在 Qt4 中编写一个应用程序。我想将事件驱动部分与从 Qt Designer 文件生成的 UI 定义分开。因此,我创建了一个“ Controller ”类,但为了简化我的生活,我还是多继承了它们。一个例子:

class BaseController(QObject):
def setupEvents(self, parent):
self.window = parent

class MainController(BaseController):
pass

class MainWindow(QMainWindow, Ui_MainWindow, MainController):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)

self.setupUi(self)
self.setupEvents(self)

这按预期工作。它还继承自 (QDialogUi_DialogBaseController)。但是,当我将 BaseController 子类化并尝试从所述子类继承(代替 BaseController)时,我收到一个错误:

TypeError: Error when calling the metaclass bases metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

澄清:QMainWindowQDialog都继承自QObjectBaseController 也必须从它继承,因为 Qt 事件系统的特性。 Ui_ 类仅继承自简单的 Python 对象类。我搜索了解决方案,但所有这些都涉及故意使用元类的情况。所以我一定是做错了什么。

编辑:通过添加图表,我的描述可能会更清晰。

工作示例:

QObject
| \___________________
| object |
QMainWindow | BaseController
| /---Ui_MainWindow |
| | MainController
MainWindow-----------------/

另一个工作示例:

QObject
| \___________________
| object |
QDialog | BaseController
| /---Ui_OtherWindow |
| | |
OtherWindow----------------/

不工作的例子:

QObject
| \___________________
| object |
QDialog | BaseController
| /---Ui_OtherWindow |
| | OtherController
OtherWindow----------------/

最佳答案

错误消息表明您在层次结构中的某处有两个冲突的元类。您需要检查每个类和 QT 类以找出冲突所在。

下面是一些设置相同情况的简单示例代码:

class MetaA(type):
pass
class MetaB(type):
pass
class A:
__metaclass__ = MetaA
class B:
__metaclass__ = MetaB

我们不能直接继承这两个类,因为 python 不知道要使用哪个元类:

>>> class Broken(A, B): pass
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Error when calling the metaclass bases
metaclass conflict: the metaclass of a derived class must be a (non-strict)
subclass of the metaclasses of all its bases

错误试图告诉我们的是,我们需要通过引入第三个元类来解决两个元类之间的冲突,该元类是基类中所有元类的子类。

我不确定这是否比错误消息本身更清楚,但基本上,您可以通过以下方式修复它:

class MetaAB(MetaA, MetaB):
pass

class Fixed(A, B):
__metaclass__ = MetaAB

此代码现在可以正确编译和运行。当然,在实际情况下,您的冲突解决元类必须决定采用哪个父元类行为,您必须根据应用程序的需求自行确定。

请记住,您的继承类只能获得两个元类中的一个__init__ 方法有时会完成所有工作,因此在很多情况下,您将不得不添加一个 __init__ 以某种方式调用两者以帮助他们相处。

关于python - 三重继承导致元类冲突......有时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6557407/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com