如何在Python中定义抽象元类

ste*_*efs 5 python abstract-class metaclass python-3.x

在 python 中定义抽象元类并实例化它时,如下所示:

from abc import ABC, abstractmethod


class AbstractMetaClass(type, ABC):
    @abstractmethod
    def func(self):
        pass


class MyClass(metaclass=AbstractMetaClass):
    pass
Run Code Online (Sandbox Code Playgroud)

我预计我的代码会失败,因为 MyClass 是抽象类的实例。相反,它运行没有问题。发生了什么事?我该怎么做?

jsb*_*eno 5

好吧,你只是发现它不起作用。你的想法是有道理的:也许它应该失败。只是抽象类并不是设计来作为元类工作的,并与“类型”协同工作。我实际上觉得不可思议,因为大多数 Python 对象机制在与元类一起使用时恰好“正常工作”——包括properties、特殊的 dunder 方法,如__getitem__和 运算符方法等。你刚刚碰到了一件事,但碰巧不起作用。

如果您的设计确实有意义,您可能只想在“抽象元类”方法上手动检查抽象方法__init__

from abc import classmethod

class AbstractMetaClass(type):

    def __init__(cls, name, bases, ns, **kwargs):
        for meth_name, meth in cls.__class__.__dict__.items():
            if getattr(meth, "__isabstractmethod__", False):
                raise TypeError(f"Can't create new class {name} with no abstract classmethod {meth_name} redefined in the metaclass")
        return super().__init__(name, bases, ns, **kwargs)
        
    @abstractmethod
    def func(cls):
        pass
Run Code Online (Sandbox Code Playgroud)

请注意,为了清楚起见,元类上的普通方法最好将“cls”作为第一个参数而不是“self”(尽管这可能是个人喜好)