【问题标题】:How to define an abstract metaclass in python如何在python中定义一个抽象元类
【发布时间】:2021-09-09 02:27:28
【问题描述】:

当在 python 中定义一个抽象元类并像这样实例化它时:

from abc import ABC, abstractmethod


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


class MyClass(metaclass=AbstractMetaClass):
    pass

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

【问题讨论】:

  • 你能在这里澄清你的用例吗?为什么需要抽象元类?
  • 你想达到什么目的? abc 模块已经提供了 ABCMeta 元类来创建抽象类。
  • 我认为实例化元类的过程绕过了ABCMeta 用来强制覆盖抽象方法的机制。它们只是不适合一起工作。
  • @chepner “不适合一起工作”是这里的关键词。

标签: python python-3.x abstract-class metaclass


【解决方案1】:

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

如果您的设计真的有意义,您可能只想手动检查“抽象元类”__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

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

【讨论】:

  • 人们甚至可以在bugs.python.org 上提出一个关于此问题的问题,但我觉得进行这项工作的请求会被拒绝。
猜你喜欢
  • 2018-06-28
  • 2011-06-16
  • 2019-12-05
  • 1970-01-01
  • 2018-07-26
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 2017-12-01
相关资源
最近更新 更多