enum — 对枚举的支持

3.4 版新增。

源代码: Lib/enum.py


枚举

  • 是一组绑定到唯一值的符号名称(成员)

  • 可以迭代以按定义顺序返回其规范(即非别名)成员

  • 使用*调用*语法按值返回成员

  • 使用*索引*语法按名称返回成员

枚举可以通过使用 class 语法或函数调用语法来创建

>>> from enum import Enum

>>> # class syntax
>>> class Color(Enum):
...     RED = 1
...     GREEN = 2
...     BLUE = 3

>>> # functional syntax
>>> Color = Enum('Color', ['RED', 'GREEN', 'BLUE'])

即使我们可以使用 class 语法来创建枚举,但枚举并不是普通的 Python 类。有关更多详细信息,请参阅 枚举有何不同?

注意

命名法

  • Color 是一个*枚举*

  • 属性 Color.REDColor.GREEN 等是*枚举成员*(或*成员*),在功能上是常量。

  • 枚举成员具有*名称*和*值*(Color.RED 的名称是 REDColor.BLUE 的值是 3,等等)


模块内容

EnumType

Enum 及其子类的 type

Enum

用于创建枚举常量的基类。

IntEnum

用于创建枚举常量的基类,这些常量也是 int 的子类。(备注

StrEnum

用于创建枚举常量的基类,这些常量也是 str 的子类。(备注

Flag

用于创建枚举常量的基类,这些常量可以使用按位运算进行组合,而不会丢失其 Flag 成员资格。

IntFlag

用于创建枚举常量的基类,这些常量可以使用按位运算符进行组合,而不会丢失其 IntFlag 成员资格。 IntFlag 成员也是 int 的子类。(备注

ReprEnum

IntEnumStrEnumIntFlag 使用,用于保留混合类型的 str()

EnumCheck

一个具有值 CONTINUOUSNAMED_FLAGSUNIQUE 的枚举,用于与 verify() 一起使用,以确保给定枚举满足各种约束。

FlagBoundary

一个具有值 STRICTCONFORMEJECTKEEP 的枚举,允许对如何在枚举中处理无效值进行更细粒度的控制。

auto

实例将替换为 Enum 成员的适当值。 StrEnum 默认为成员名称的小写版本,而其他枚举默认为 1 并从那里开始递增。

property()

允许 Enum 成员具有属性,而不会与成员名称冲突。 valuename 属性就是以这种方式实现的。

unique()

枚举类装饰器,确保只有一个名称绑定到任何一个值。

verify()

枚举类装饰器,用于检查枚举上的用户可选约束。

member()

使 obj 成为成员。可以用作装饰器。

nonmember()

不要使 obj 成为成员。可以用作装饰器。

global_enum()

修改枚举的 str()repr(),以将其成员显示为属于模块而不是其类,并将枚举成员导出到全局命名空间。

show_flag_values()

返回标志中包含的所有 2 的幂次整数的列表。

3.6 版新增: FlagIntFlagauto

3.11 版新增: StrEnumEnumCheckReprEnumFlagBoundarypropertymembernonmemberglobal_enumshow_flag_values


数据类型

class enum.EnumType

EnumTypeenum 枚举的 元类。可以子类化 EnumType – 有关详细信息,请参阅 子类化 EnumType

EnumType 负责在最终的 enum 上设置正确的 __repr__()__str__()__format__()__reduce__() 方法,以及创建枚举成员、正确处理重复项、提供对枚举类的迭代等。

__call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

此方法以两种不同的方式调用

  • 查找现有成员

    cls:

    被调用的枚举类。

    value:

    要查找的值。

  • 使用 cls 枚举创建新的枚举(仅当现有枚举没有任何成员时)

    cls:

    被调用的枚举类。

    value:

    要创建的新枚举的名称。

    names:

    新枚举的成员的名称/值。

    module:

    创建新枚举的模块的名称。

    qualname:

    模块中可以找到此枚举的实际位置。

    type:

    新枚举的混合类型。

    start:

    枚举的第一个整数值(由 auto 使用)。

    boundary:

    如何处理位运算产生的超出范围的值(仅限 Flag)。

__contains__(cls, member)

如果成员属于 cls,则返回 True

>>> some_var = Color.RED
>>> some_var in Color
True
>>> Color.RED.value in Color
True

在 3.12 版更改: 在 Python 3.12 之前,如果在包含检查中使用了非枚举成员,则会引发 TypeError

__dir__(cls)

返回 ['__class__', '__doc__', '__members__', '__module__'] 以及 cls 中成员的名称

>>> dir(Color)
['BLUE', 'GREEN', 'RED', '__class__', '__contains__', '__doc__', '__getitem__', '__init_subclass__', '__iter__', '__len__', '__members__', '__module__', '__name__', '__qualname__']
__getitem__(cls, name)

返回 cls 中与 name 匹配的枚举成员,或者引发 KeyError

>>> Color['BLUE']
<Color.BLUE: 3>
__iter__(cls)

按定义顺序返回 cls 中的每个成员

>>> list(Color)
[<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 3>]
__len__(cls)

返回 cls 中的成员数量

>>> len(Color)
3
__members__

返回每个枚举名称到其成员的映射,包括别名

__reversed__(cls)

按反向定义顺序返回 cls 中的每个成员

>>> list(reversed(Color))
[<Color.BLUE: 3>, <Color.GREEN: 2>, <Color.RED: 1>]

3.11 版新增: 在 3.11 之前,enum 使用 EnumMeta 类型,该类型保留为别名。

class enum.Enum

Enum 是所有 enum 枚举的基类。

name

用于定义 Enum 成员的名称

>>> Color.BLUE.name
'BLUE'
value

赋予 Enum 成员的值

>>> Color.RED.value
1

成员的值,可以在 __new__() 中设置。

注意

枚举成员值

成员值可以是任何值:intstr 等。如果确切的值不重要,则可以使用 auto 实例,并且会为您选择一个适当的值。有关详细信息,请参阅 auto

虽然可以使用可变/不可哈希值,例如 dictlist 或可变的 dataclass,但相对于枚举中可变/不可哈希值的总数,它们在创建过程中会对性能产生二次影响。

_name_

成员的名称。

_value_

成员的值,可以在 __new__() 中设置。

_order_

不再使用,保留是为了向后兼容。(类属性,在类创建期间删除)。

_ignore_

_ignore_ 仅在创建期间使用,并在创建完成后从枚举中删除。

_ignore_ 是一个名称列表,这些名称不会成为成员,并且其名称也将从完成的枚举中删除。有关示例,请参阅 TimePeriod

__dir__(self)

返回 ['__class__', '__doc__', '__module__', 'name', 'value'] 以及在 self.__class__ 上定义的任何公共方法

>>> from datetime import date
>>> class Weekday(Enum):
...     MONDAY = 1
...     TUESDAY = 2
...     WEDNESDAY = 3
...     THURSDAY = 4
...     FRIDAY = 5
...     SATURDAY = 6
...     SUNDAY = 7
...     @classmethod
...     def today(cls):
...         print('today is %s' % cls(date.today().isoweekday()).name)
...
>>> dir(Weekday.SATURDAY)
['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'today', 'value']
_generate_next_value_(name, start, count, last_values)
name

正在定义的成员的名称(例如“RED”)。

start:

枚举的起始值;默认为 1。

count

当前定义的成员数量,不包括此成员。

last_values

先前值的列表。

一个用于确定 auto 返回的下一个值的 *静态方法*

>>> from enum import auto
>>> class PowersOfThree(Enum):
...     @staticmethod
...     def _generate_next_value_(name, start, count, last_values):
...         return 3 ** (count + 1)
...     FIRST = auto()
...     SECOND = auto()
...
>>> PowersOfThree.SECOND.value
9
__init__(self, *args, **kwds)

默认情况下,不执行任何操作。如果在成员赋值中给出了多个值,则这些值将成为 __init__ 的单独参数;例如

>>> from enum import Enum
>>> class Weekday(Enum):
...     MONDAY = 1, 'Mon'

Weekday.__init__() 将被调用为 Weekday.__init__(self, 1, 'Mon')

__init_subclass__(cls, **kwds)

一个用于进一步配置后续子类的 *类方法*。默认情况下,不执行任何操作。

_missing_(cls, value)

一个用于查找在 *cls* 中找不到的值的 *类方法*。默认情况下,它不执行任何操作,但可以重写以实现自定义搜索行为

>>> from enum import StrEnum
>>> class Build(StrEnum):
...     DEBUG = auto()
...     OPTIMIZED = auto()
...     @classmethod
...     def _missing_(cls, value):
...         value = value.lower()
...         for member in cls:
...             if member.value == value:
...                 return member
...         return None
...
>>> Build.DEBUG.value
'debug'
>>> Build('deBUG')
<Build.DEBUG: 'debug'>
__new__(cls, *args, **kwds)

默认情况下,不存在。如果指定,无论是在枚举类定义中还是在混入类(例如 int)中,成员赋值中给出的所有值都将被传递;例如

>>> from enum import Enum
>>> class MyIntEnum(int, Enum):
...     TWENTYSIX = '1a', 16

导致调用 int('1a', 16) 并为该成员赋值 26

注意

编写自定义 __new__ 时,不要使用 super().__new__ – 请调用相应的 __new__

__repr__(self)

返回用于 *repr()* 调用的字符串。默认情况下,返回 *Enum* 名称、成员名称和值,但可以重写

>>> class OtherStyle(Enum):
...     ALTERNATE = auto()
...     OTHER = auto()
...     SOMETHING_ELSE = auto()
...     def __repr__(self):
...         cls_name = self.__class__.__name__
...         return f'{cls_name}.{self.name}'
...
>>> OtherStyle.ALTERNATE, str(OtherStyle.ALTERNATE), f"{OtherStyle.ALTERNATE}"
(OtherStyle.ALTERNATE, 'OtherStyle.ALTERNATE', 'OtherStyle.ALTERNATE')
__str__(self)

返回用于 *str()* 调用的字符串。默认情况下,返回 *Enum* 名称和成员名称,但可以重写

>>> class OtherStyle(Enum):
...     ALTERNATE = auto()
...     OTHER = auto()
...     SOMETHING_ELSE = auto()
...     def __str__(self):
...         return f'{self.name}'
...
>>> OtherStyle.ALTERNATE, str(OtherStyle.ALTERNATE), f"{OtherStyle.ALTERNATE}"
(<OtherStyle.ALTERNATE: 1>, 'ALTERNATE', 'ALTERNATE')
__format__(self)

返回用于 *format()* 和 *f-string* 调用的字符串。默认情况下,返回 __str__() 返回值,但可以重写

>>> class OtherStyle(Enum):
...     ALTERNATE = auto()
...     OTHER = auto()
...     SOMETHING_ELSE = auto()
...     def __format__(self, spec):
...         return f'{self.name}'
...
>>> OtherStyle.ALTERNATE, str(OtherStyle.ALTERNATE), f"{OtherStyle.ALTERNATE}"
(<OtherStyle.ALTERNATE: 1>, 'OtherStyle.ALTERNATE', 'ALTERNATE')

注意

autoEnum 一起使用会导致整数值递增,从 1 开始。

在 3.12 版更改: 添加了数据类支持

class enum.IntEnum

*IntEnum* 与 *Enum* 相同,但其成员也是整数,并且可以在可以使用整数的任何地方使用。如果使用 *IntEnum* 成员执行任何整数运算,则结果值将失去其枚举状态。

>>> from enum import IntEnum
>>> class Number(IntEnum):
...     ONE = 1
...     TWO = 2
...     THREE = 3
...
>>> Number.THREE
<Number.THREE: 3>
>>> Number.ONE + Number.TWO
3
>>> Number.THREE + 5
8
>>> Number.THREE == 3
True

注意

autoIntEnum 一起使用会导致整数值递增,从 1 开始。

在 3.11 版更改: __str__() 现在是 int.__str__(),以便更好地支持 *替换现有常量* 的用例。__format__() 出于相同的原因已经是 int.__format__()

class enum.StrEnum

*StrEnum* 与 *Enum* 相同,但其成员也是字符串,并且可以在可以使用字符串的大多数地方使用。对 *StrEnum* 成员执行或与其一起执行的任何字符串操作的结果都不是枚举的一部分。

注意

stdlib 中有些地方会检查精确的 str 而不是 str 子类(即 type(unknown) == str 而不是 isinstance(unknown, str)),在这些地方,您需要使用 str(StrEnum.member)

注意

autoStrEnum 一起使用会导致小写的成员名称作为值。

注意

__str__()str.__str__(),以便更好地支持 *替换现有常量* 的用例。__format__() 出于相同的原因也是 str.__format__()

3.11 版新增。

class enum.Flag

FlagEnum 相同,但其成员支持按位运算符 &(*AND*)、|(*OR*)、^(*XOR*)和 ~(*INVERT*);这些操作的结果是枚举的成员(的别名)。

__contains__(self, value)

如果 value 在 self 中,则返回 *True*

>>> from enum import Flag, auto
>>> class Color(Flag):
...     RED = auto()
...     GREEN = auto()
...     BLUE = auto()
...
>>> purple = Color.RED | Color.BLUE
>>> white = Color.RED | Color.GREEN | Color.BLUE
>>> Color.GREEN in purple
False
>>> Color.GREEN in white
True
>>> purple in white
True
>>> white in purple
False
__iter__(self)

返回所有包含的非别名成员

>>> list(Color.RED)
[<Color.RED: 1>]
>>> list(purple)
[<Color.RED: 1>, <Color.BLUE: 4>]

3.11 版新增。

__len__(self)

返回标志中的成员数量

>>> len(Color.GREEN)
1
>>> len(white)
3
__bool__(self)

如果标志中存在任何成员,则返回 *True*,否则返回 *False*

>>> bool(Color.GREEN)
True
>>> bool(white)
True
>>> black = Color(0)
>>> bool(black)
False
__or__(self, other)

返回当前标志与 other 进行二进制或运算的结果

>>> Color.RED | Color.GREEN
<Color.RED|GREEN: 3>
__and__(self, other)

返回当前标志与 other 进行二进制与运算的结果

>>> purple & white
<Color.RED|BLUE: 5>
>>> purple & Color.GREEN
<Color: 0>
__xor__(self, other)

返回当前标志与 other 进行二进制异或运算的结果

>>> purple ^ white
<Color.GREEN: 2>
>>> purple ^ Color.GREEN
<Color.RED|GREEN|BLUE: 7>
__invert__(self)

返回 type(self) 中所有不在 self 中的标志

>>> ~white
<Color: 0>
>>> ~purple
<Color.GREEN: 2>
>>> ~Color.RED
<Color.GREEN|BLUE: 6>
_numeric_repr_()

用于格式化任何剩余的未命名数值的函数。默认值为该值的 repr;常见的选择是 hex()oct()

注意

autoFlag 一起使用会导致整数为 2 的幂,从 1 开始。

版本 3.11 中变更: 零值标志的 repr() 已更改。现在是:

>>> Color(0) 
<Color: 0>
class enum.IntFlag

IntFlagFlag 相同,但其成员也是整数,并且可以在可以使用整数的任何地方使用。

>>> from enum import IntFlag, auto
>>> class Color(IntFlag):
...     RED = auto()
...     GREEN = auto()
...     BLUE = auto()
...
>>> Color.RED & 2
<Color: 0>
>>> Color.RED | 2
<Color.RED|GREEN: 3>

如果使用 IntFlag 成员执行任何整数运算,则结果不是 IntFlag

>>> Color.RED + 2
3

如果使用 IntFlag 成员执行 Flag 运算,并且

  • 结果是有效的 IntFlag:则返回 IntFlag

  • 结果不是有效的 IntFlag:结果取决于 FlagBoundary 设置

未命名的零值标志的 repr() 已更改。现在是

>>> Color(0)
<Color: 0>

注意

autoIntFlag 一起使用会导致整数为 2 的幂,从 1 开始。

在 3.11 版更改: __str__() 现在是 int.__str__(),以便更好地支持 *替换现有常量* 的用例。__format__() 出于相同的原因已经是 int.__format__()

IntFlag 的反转现在返回一个正值,该值是不在给定标志中的所有标志的并集,而不是负值。这与现有的 Flag 行为相匹配。

class enum.ReprEnum

ReprEnum 使用 repr()Enum,但使用混合数据类型的 str()

继承自 ReprEnum 以保留混合数据类型的 str() / format(),而不是使用 Enum 默认的 str()

3.11 版新增。

class enum.EnumCheck

EnumCheck 包含 verify() 装饰器用来确保各种约束的选项;失败的约束会导致 ValueError

UNIQUE

确保每个值只有一个名称

>>> from enum import Enum, verify, UNIQUE
>>> @verify(UNIQUE)
... class Color(Enum):
...     RED = 1
...     GREEN = 2
...     BLUE = 3
...     CRIMSON = 1
Traceback (most recent call last):
...
ValueError: aliases found in <enum 'Color'>: CRIMSON -> RED
CONTINUOUS

确保在值最低的成员和值最高的成员之间没有缺失值

>>> from enum import Enum, verify, CONTINUOUS
>>> @verify(CONTINUOUS)
... class Color(Enum):
...     RED = 1
...     GREEN = 2
...     BLUE = 5
Traceback (most recent call last):
...
ValueError: invalid enum 'Color': missing values 3, 4
NAMED_FLAGS

确保任何标志组/掩码仅包含已命名的标志 - 当指定值而不是由 auto() 生成值时非常有用

>>> from enum import Flag, verify, NAMED_FLAGS
>>> @verify(NAMED_FLAGS)
... class Color(Flag):
...     RED = 1
...     GREEN = 2
...     BLUE = 4
...     WHITE = 15
...     NEON = 31
Traceback (most recent call last):
...
ValueError: invalid Flag 'Color': aliases WHITE and NEON are missing combined values of 0x18 [use enum.show_flag_values(value) for details]

注意

CONTINUOUS 和 NAMED_FLAGS 旨在与整数值成员一起使用。

3.11 版新增。

class enum.FlagBoundary

FlagBoundary 控制如何在 Flag 及其子类中处理超出范围的值。

STRICT

超出范围的值会导致引发 ValueError。这是 Flag 的默认行为

>>> from enum import Flag, STRICT, auto
>>> class StrictFlag(Flag, boundary=STRICT):
...     RED = auto()
...     GREEN = auto()
...     BLUE = auto()
...
>>> StrictFlag(2**2 + 2**4)
Traceback (most recent call last):
...
ValueError: <flag 'StrictFlag'> invalid value 20
    given 0b0 10100
  allowed 0b0 00111
CONFORM

超出范围的值会被移除无效值,留下有效的 Flag

>>> from enum import Flag, CONFORM, auto
>>> class ConformFlag(Flag, boundary=CONFORM):
...     RED = auto()
...     GREEN = auto()
...     BLUE = auto()
...
>>> ConformFlag(2**2 + 2**4)
<ConformFlag.BLUE: 4>
EJECT

超出范围的值会失去其 Flag 成员资格,并恢复为 int

>>> from enum import Flag, EJECT, auto
>>> class EjectFlag(Flag, boundary=EJECT):
...     RED = auto()
...     GREEN = auto()
...     BLUE = auto()
...
>>> EjectFlag(2**2 + 2**4)
20
KEEP

超出范围的值会被保留,并且 Flag 成员资格也会保留。这是 IntFlag 的默认行为

>>> from enum import Flag, KEEP, auto
>>> class KeepFlag(Flag, boundary=KEEP):
...     RED = auto()
...     GREEN = auto()
...     BLUE = auto()
...
>>> KeepFlag(2**2 + 2**4)
<KeepFlag.BLUE|16: 20>

3.11 版新增。


支持的 __dunder__ 名称

__members__ 是一个只读的有序映射,包含 member_name:member 键值对。它只能在类上使用。

__new__() 如果指定,则必须创建并返回枚举成员;最好也适当地设置成员的 _value_。一旦所有成员都被创建,它就不再被使用。

支持的 _sunder_ 名称

  • _name_ – 成员的名称

  • _value_ – 成员的值;可以在 __new__ 中设置

  • _missing_() – 当找不到值时使用的查找函数;可以被重写

  • _ignore_ – 一个名称列表,可以是 liststr,这些名称不会被转换为成员,并且将从最终类中删除

  • _order_ – 不再使用,保留是为了向后兼容(类属性,在类创建期间删除)

  • _generate_next_value_() – 用于获取枚举成员的适当值;可以被重写

    注意

    对于标准的 Enum 类,选择的下一个值是最后一个值加一。

    对于 Flag 类,选择的下一个值将是下一个更高的 2 的幂,而不管最后一个值是什么。

3.6 版新增: _missing__order__generate_next_value_

3.7 版新增: _ignore_


实用程序和装饰器

class enum.auto

auto 可以用来代替值。如果使用,Enum 机制将调用 Enum_generate_next_value_() 来获取适当的值。对于 EnumIntEnum,适当的值将是最后一个值加一;对于 FlagIntFlag,它将是大于最高值的第一个 2 的幂;对于 StrEnum,它将是成员名称的小写版本。如果将 auto() 与手动指定的值混合使用,则必须小心。

auto 实例仅在赋值的顶层解析

  • FIRST = auto() 将起作用(auto() 被替换为 1);

  • SECOND = auto(), -2 将起作用(auto 被替换为 2,因此使用 2, -2 创建 SECOND 枚举成员);

  • THREE = [auto(), -3]不起作用(使用 <auto instance>, -3 创建 THREE 枚举成员)

在 3.11.1 版更改: 在以前的版本中,auto() 必须是赋值行中唯一的内容才能正常工作。

可以重写 _generate_next_value_ 来自定义 auto 使用的值。

注意

在 3.13 中,默认的 _generate_next_value_ 将始终返回递增 1 的最高成员值,如果任何成员是 incompatible 类型,则会失败。

@enum.property

一个类似于内置 property 的装饰器,但专门用于枚举。它允许成员属性与成员本身具有相同的名称。

注意

property 和成员必须在不同的类中定义;例如,valuename 属性在 Enum 类中定义,而 Enum 子类可以定义名为 valuename 的成员。

3.11 版新增。

@enum.unique

一个专门用于枚举的 class 装饰器。它搜索枚举的 __members__,收集它找到的任何别名;如果找到任何别名,则会引发带有详细信息的 ValueError

>>> from enum import Enum, unique
>>> @unique
... class Mistake(Enum):
...     ONE = 1
...     TWO = 2
...     THREE = 3
...     FOUR = 3
...
Traceback (most recent call last):
...
ValueError: duplicate values found in <enum 'Mistake'>: FOUR -> THREE
@enum.verify

一个专门用于枚举的 class 装饰器。来自 EnumCheck 的成员用于指定应在装饰的枚举上检查哪些约束。

3.11 版新增。

@enum.member

一个用于枚举的装饰器:它的目标将成为一个成员。

3.11 版新增。

@enum.nonmember

一个用于枚举的装饰器:它的目标将不会成为一个成员。

3.11 版新增。

@enum.global_enum

一个装饰器,用于更改枚举的 str()repr(),以显示其成员属于模块而不是其类。仅当枚举成员导出到模块全局命名空间时才应使用(有关示例,请参见 re.RegexFlag)。

3.11 版新增。

enum.show_flag_values(value)

返回包含在标志 value 中的所有 2 的幂的整数列表。

3.11 版新增。


备注

IntEnumStrEnumIntFlag

这三种枚举类型被设计为现有基于整数和字符串的值的直接替代品;因此,它们有一些额外的限制

  • __str__ 使用枚举成员的值而不是名称

  • __format__,因为它使用 __str__,也将使用枚举成员的值而不是其名称

如果您不需要/不想要这些限制,您可以通过自己混合 intstr 类型来创建自己的基类

>>> from enum import Enum
>>> class MyIntEnum(int, Enum):
...     pass

或者您可以在枚举中重新分配适当的 str()

>>> from enum import Enum, IntEnum
>>> class MyIntEnum(IntEnum):
...     __str__ = Enum.__str__