子类枚举添加验证

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

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__
来实现吗?是否还有另一种方法可以使用——也许是在枚举完全创建后调用的方法?

python enums
2个回答
3
投票

我不知道如何子类化

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 

2
投票

__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
)
库的作者。

© www.soinside.com 2019 - 2024. All rights reserved.