gpt4 book ai didi

python - 使用 ABCMeta 和 EnumMeta 抽象枚举类

转载 作者:太空宇宙 更新时间:2023-11-03 13:56:30 24 4
gpt4 key购买 nike

<分区>

简单示例

目标是通过从 abc.ABCMetaenum.EnumMeta 派生的元类创建抽象枚举类。例如:

import abc
import enum

class ABCEnumMeta(abc.ABCMeta, enum.EnumMeta):
pass

class A(abc.ABC):
@abc.abstractmethod
def foo(self):
pass

class B(A, enum.IntEnum, metaclass=ABCEnumMeta):
X = 1

class C(A):
pass

现在,在 Python3.7 上,这段代码将被无误地解释(在 3.6.x 上,大概在以下,它不会)。事实上,一切看起来都很棒,我们的 MRO 显示 B 派生自 AIntEnum

>>> B.__mro__
(<enum 'B'>, __main__.A, abc.ABC, <enum 'IntEnum'>, int, <enum 'Enum'>, object)

抽象枚举不是抽象

然而,即使B.foo没有被定义,我们仍然可以毫无问题地实例化B,并调用foo() .

>>> B.X
<B.X: 1>
>>> B(1)
<B.X: 1>
>>> B(1).foo()

这看起来很奇怪,因为从 ABCMeta 派生的任何其他类都无法实例化,即使我使用自定义元类也是如此。

>>> class NewMeta(type): 
... pass
...
... class AbcNewMeta(abc.ABCMeta, NewMeta):
... pass
...
... class D(metaclass=NewMeta):
... pass
...
... class E(A, D, metaclass=AbcNewMeta):
... pass
...
>>> E()
TypeError: Can't instantiate abstract class E with abstract methods foo

问题

为什么使用从 EnumMetaABCMeta 派生的元类的类有效地忽略 ABCMeta,而使用从 派生的元类的任何其他类code>ABCMeta 使用它?即使我自定义定义了 __new__ 运算符也是如此。

class ABCEnumMeta(abc.ABCMeta, enum.EnumMeta):
def __new__(cls, name, bases, dct):
# Commented out lines reflect other variants that don't work
#return abc.ABCMeta.__new__(cls, name, bases, dct)
#return enum.EnumMeta.__new__(cls, name, bases, dct)
return super().__new__(cls, name, bases, dct)

我很困惑,因为这似乎与什么是元类背道而驰:元类应该定义类的定义和行为方式,在这种情况下,使用抽象的元类定义类并且枚举创建了一个静默忽略抽象组件的类。这是一个错误,这是故意的,还是我不理解的更重要的事情?

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com