我有一组继承自元类的插件。元类的定义如下:
from abc import ABC, abstractmethod
class MetaReader(ABC):
def __init__(self, arg1, arg2, **kwargs):
...
子类如下:
from utils.MetaReader import MetaReader
class ABF2Reader(MetaReader):
...
据我所知,这是可行的,我可以实例化类并按预期使用它们。然而,在某些时候,我需要将这些类作为插件加载而不实例化它们,当我这样做时,我需要根据正确的元类检查它们的子类,以了解加载时如何处理它们。在那里,我得到了一些奇怪的结果:
from utils.MetaReader import MetaReader
from plugins.datareaders.ABF2Reader import ABF2Reader
print(type(reader)) #reader is an instance of ABF2Reader
print(type(MetaReader)) #MetaReader is just the metaclass, not instantiated
print(type(ABF2Reader)) #Just the subclass, not instantiated
打印:
<class 'plugins.datareaders.ABF2Reader.ABF2Reader'>
<class 'abc.ABCMeta'>
<class 'abc.ABCMeta'>
reader
的类型正是我所期望的:它是 ABF2Reader 的一个实例。但其他两个的类型则不然。 type(MetaReader)
也很好,但我希望type(ABF2Reader)
给我<class 'MetaReader'>
,而不是<class 'abc.ABCMeta'>
显然我错误地使用了元类。有人可以阐明我在哪里搞砸了吗?
此代码没有定义任何新的元类来开始。 事实是,无论如何您可能都不需要自定义元类 - 如果您说出使用元类的意图,就有可能知道。但事实上,我们只有一个 2 类层次结构,什么也不做。
因此,
abc.ABC
,您从中继承的是一个类,而不是元类,这使得它的子类与 abc.abstractmethod
装饰器一起使用,并允许其他不相关的类使用 myclass.register
注册为它们自己的虚拟子类
方法。
发生的情况是
abc.ABC
本身使用自定义元类,即 abc.ABCMeta
类 - 并且您没有显示任何想要自定义它的原因。无论如何,这就是为什么 type(MetaReader)
输出 ABCMeta:它的元类,这意味着“MetaReader”类本身就是一个实例的类,是 abc.ABCMeta
,通过继承 abc.ABC
。
要将自定义元类应用于您自己的类,您首先必须通过从
type
继承它来创建这样的元类,或者在本例中从 abc.ABCMeta
(继承自 type
)。然后,在声明类时,必须使用命名参数 metaclass=MyMetaClass
以及类基数:
class MetaReader(abc.ABCMeta):
# body which actually makes something useful on class
# creation time, or the class behavior itself,
# and which can´t be done by __init_subclass__
# (usually by overriding __new__ or __call__ ) ...
class ABF2Reader(abc.ABC, metaclass=MetaReader):
...