从ABC和QMainWindow继承的抽象类[重复]

Posted

技术标签:

【中文标题】从ABC和QMainWindow继承的抽象类[重复]【英文标题】:Abstract class inheriting from ABC and QMainWindow [duplicate] 【发布时间】:2021-09-19 02:05:18 【问题描述】:
from abc import ABC, abstractmethod
from PyQt5.QtWidgets import QMainWindow


class _ControlGUI(QMainWindow, ABC):
    pass

上面非常简单的代码引发了一个我不太清楚的错误。

TypeError: 元类冲突:派生类的元类必须 是其所有基类的元类的(非严格)子类

我的目标是定义一个具有强制结构/属性的基类_ControlGUI;然后定义多个继承自它的具体类,并具有额外的功能/属性。所有这些具体类都是小的 GUI,因此继承自 QMainWindow,因此我认为最好让抽象类直接从 QMainWindow 继承。但是,这似乎是不可能的。

什么是最好的设计,解决这个问题?我目前的想法是定义没有QMainWindow 的抽象类,并让所有具体类继承自_ControlGUIQMainWindow

【问题讨论】:

这是元类的问题;他们写得不好。 _ControlGUI 的子类也不能从 QMainWindow 继承;这是QMainWindow 使用的元类与ABCMeta 冲突。 据我所知,唯一的解决方案是不使用ABC,而是依靠子类来实现记录为需要重写的方法。 还有一个事实是 PyQt 类并不总是与多重继承很好地混合在一起,因此必须格外小心,尤其是在处理构造函数中的参数时。请参阅 this 和 this。如果您能提供一个基本的minimal reproducible example 来说明您正在努力实现的目标,我们或许能够更好地了解问题出在哪里,看看是否还有其他可能性。 您可以定义class YourMetaClass(type(QMainWindow), type(ABC)): pass 然后在class _ControlGUI(QMainWindow, ABC, metaclass=YourMetaClass): 中指定。 Maybe this will help @JulianFock 我给了你一个答案。看起来它运作良好!随意输入它作为这个问题的完整答案。 【参考方案1】:

正如错误所说,您必须创建一个元类,它是所涉及类的每个元类的子类。

PyQT Widgets 的元类可能不是为了与其他元类协作而设计的——这将是一个运气问题。 ABC 的元类abc.ABCMeta(出于说明目的,我在下面将其称为type(ABC))如果更适合协作继承,那么在派生元类时将其放在首位将使您有更好的机会让事情真正发挥作用。 (即,除其他外,它将在其方法中使用super() 调用,而不是对type.<method> 的调用进行硬编码)。

获得派生元类后,只需在继承的基类上使用它即可。由于所有的例子都是一行代码,而且查看结果很有趣,我只是在交互环境上写了一些东西:

In [1]: from PyQt5.QtWidgets import QMainWindow

In [2]: from abc import ABC, ABCMeta

In [3]: class A(QMainWindow, ABC): pass
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-86552c93e708> in <module>
----> 1 class A(QMainWindow, ABC): pass

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

In [4]: class Meta(type(ABC), type(QMainWindow)): pass

In [5]: class B(QMainWindow, ABC, metaclass=Meta): pass

附带说明一下,无论 Qt 文档(以及其他图形工具包)怎么说,使用小部件的子类来创建您的应用程序可能会很痛苦。如果您只是实例化这些小部件并将它们作为一个普通类中的属性引用,只继承与您的项目有关的东西,那么与从QMainWindow 继承相比,您可能会走上一段更好的旅程。

【讨论】:

(对不起,我写了答案,然后我停下来检查了 cmets。这也是一个明显的重复,并且在 [metaclass] 上搜索至少 3 次会产生同样的问题。但是因为我喜欢在每次弹出时写一些额外的建议,所以我只是输入了答案) 谢谢你,确实感谢评论我有一个类似的工作解决方案,但是 Meta 中的顺序是相反的。这个元类的想法和它代表的东西对我来说还不是很清楚,我会继续寻找。对于 Qt 部分,是的,它可能要好得多,但我对 Qt 一点也不熟悉,完全改变项目的结构(我不是原作者)会很痛苦。

以上是关于从ABC和QMainWindow继承的抽象类[重复]的主要内容,如果未能解决你的问题,请参考以下文章

从 QMainWindow 和 Ui_MainWindow 继承 MainWindow 类

使用PyQt(QMainWindow)使用多重继承进行子类化时python中的MRO [重复]

如何从用 C# 编写的抽象基类继承

python 抽象基类(abc)

抽象类与归一化

Python基础(17)_面向对象程序设计(抽象类继承原理封装多态,绑定方法)