创建继承自 ABCMeta 和 QObject 的元类

问题描述 投票:0回答:1

我正在 PySide6 中构建一个应用程序,它将涉及插件的动态加载。为了实现这一点,我使用

ABCMeta
为插件接口定义一个自定义元类,并且我希望这个自定义元类从
ABC
QObject
继承,以便我可以抽象尽可能多的行为,包括所有子类通用的标准信号和槽之类的东西。

我已经建立了一个 MWE,它显示了使我能够使此设置正常工作的逻辑链,但继承链比我想象的要更深,并且 ABC 的执行似乎并没有贯彻执行(从某种意义上说,不覆盖

@abstractmethod
不会导致错误)。是否可以在保留所需继承的同时缩短此时间?最后,我的目标是让
print_value()
类作为继承自 ABC 的抽象基类,以便我可以在其中定义
MetaTab
,然后为各个插件创建子类。我真的需要
@abstractmethod
QABCMeta
来完成这项工作,还是有办法清理它,消除这个继承链中的一个链接?
QObjectMeta

	
python abstract-class multiple-inheritance metaclass pyside6
1个回答
0
投票

我发现的解决方法是在元类中重新实现 ABCMeta 的一些行为,该元类结合了 QOBjects 的元类和 ABCMeta 本身 - 通过以下更改,

from abc import ABC, ABCMeta, abstractmethod from PySide6.QtCore import QObject class QABCMeta(ABCMeta, type(QObject)): pass class QObjectMeta(ABC, metaclass=QABCMeta): pass class MetaTab(QObject, QObjectMeta): def __init__(self, x): print('initialized') self.x = x @abstractmethod def print_value(self): pass class Tab(MetaTab): def __init__(self, x): super().__init__(x) def print_value(self): print(self.x) def main(): obj = Tab(5) for b in obj.__class__.__bases__: print("Base class name:", b.__name__) print("Class name:", obj.__class__.__name__) obj.print_value() if __name__=='__main__': main()

行为将恢复:

@abstractmethod

使用从“MetaTab”派生的类(未实现 
class QABCMeta(ABCMeta, type(QObject)): def __new__(mcls, name, bases, ns, **kw): cls = super().__new__(mcls, name, bases, ns, **kw) abc._abc_init(cls) return cls def __call__(cls, *args, **kw): if cls.__abstractmethods__: raise TypeError(f"Can't instantiate abstract class {cls.__name__} without an implementation for abstract methods {set(cls.__abstractmethods__)}") return super().__call__(*args, **kw)

)在 REPL 上进行测试将按预期引发:

print_value

至于您构建的层次结构:您可能可以跳过一些中间类,但我要更改的是避免使用名称“Meta”来表示
不是

元类(即用于构建类的类)它们本身,并且被传递给 In [112]: class T2(MetaTab): ...: pass ...: In [113]: T2(1) --------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[113], line 1 ----> 1 T2(1) Cell In[105], line 11, in QABCMeta.__call__(cls, *args, **kw) (...) Can't instantiate abstract class T2 without an implementation for abstract methods : {'print_value'}) 命名参数) - QObjectMeta 和 MetaTab 都是令人困惑的名称,因此 - 您可以使用“Base”或“Mixin”之类的中缀来代替。

也就是说,您称为 

metaclass=

的课程可能只是:

QobjectMeta

然后你的“MetaTab”就不需要显式地从 QObject 继承。
(不需要从 ABC 显式继承并恢复元类行为):

class AQObjectBase(QObject, metaclass=QABCMeta): pass

	
© www.soinside.com 2019 - 2024. All rights reserved.