根据元类类型检查子类

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

我有一组继承自元类的插件。元类的定义如下:

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'>

显然我错误地使用了元类。有人可以阐明我在哪里搞砸了吗?

python-3.x types metaclass abc
1个回答
0
投票

此代码没有定义任何新的元类来开始。 事实是,无论如何您可能都不需要自定义元类 - 如果您说出使用元类的意图,就有可能知道。但事实上,我们只有一个 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):
    ...
© www.soinside.com 2019 - 2024. All rights reserved.