enum
模块的Python
docs包含以下子类化
Enum
示例。生成的类可用于创建枚举,该枚举还验证它们不存在具有相同值的两个成员。
>>> class DuplicateFreeEnum(Enum):
... def __init__(self, *args):
... cls = self.__class__
... if any(self.value == e.value for e in cls):
... a = self.name
... e = cls(self.value).name
... raise ValueError(
... "aliases not allowed in DuplicateFreeEnum: %r --> %r"
... % (a, e))
但是,作为一种添加验证的方法,这种方法不够优雅且具有限制性。
__init__
为每个成员调用一次,而为了验证整个枚举,一起查看枚举的每个成员更有意义。
例如,我如何验证枚举是否恰好有两个成员,如下所示?
class PreciselyTwoEnum(Enum):
... # ???
class Allowed(PreciselyTwoEnum):
FOO = 1
BAR = 2
class Disallowed(PreciselyTwoEnum): # Should raise an error
BAZ = 3
这可以通过巧妙地实现
__init__
来实现吗?是否还有另一种方法可以使用——也许是在枚举完全创建后调用的方法?
我不知道如何子类化
Enum
来实现所需的功能,但可以使用类装饰器轻松完成:
from enum import Enum
def PreciselyTwoEnum(cls):
members = len(cls.__members__)
if members != 2:
raise ValueError(f"two members expected in {cls.__name__!r}, but got {members}")
return cls
@PreciselyTwoEnum
class Allowed(Enum):
FOO = 1
BAR = 2
@PreciselyTwoEnum
class Disallowed(Enum): # Should raise an error
BAZ = 3
__init_subclass__
就是您正在寻找的1:
class PreciselyTwoEnum(Enum):
def __init_subclass__(cls):
if len(cls.__members__) != 2:
raise TypeError("only two members allowed")
使用中:
>>> class Allowed(PreciselyTwoEnum):
... FOO = 1
... BAR = 2
...
>>> class Disallowed(PreciselyTwoEnum): # Should raise an error
... BAZ = 3
...
Traceback (most recent call last):
...
TypeError: only two members allowed
[1]
__init_subclass__
对于 Enum
仅在 Python 3.11 或更高版本中才能正常工作,或者使用外部 aenum
库 v3.0 或更高版本。2.
[2] 披露:我是 Python stdlib
Enum
、enum34
backport 和 Advanced Enumeration (aenum
) 库的作者。