enumSupport for enumerations支持枚举

New in version 3.4.版本3.4中新增。

Source code: Lib/enum.py


An enumeration is a set of symbolic names (members) bound to unique, constant values. 枚举是绑定到唯一常量值的一组符号名(成员)。Within an enumeration, the members can be compared by identity, and the enumeration itself can be iterated over.在枚举中,成员可以通过标识进行比较,枚举本身可以迭代。

Note

Case of Enum Members枚举成员的情况

Because Enums are used to represent constants we recommend using UPPER_CASE names for enum members, and will be using that style in our examples.由于枚举用于表示常量,我们建议对枚举成员使用大写名称,并将在示例中使用该样式。

Module Contents模块内容

This module defines four enumeration classes that can be used to define unique sets of names and values: Enum, IntEnum, Flag, and IntFlag. 该模块定义了四个枚举类,可用于定义唯一的名称和值集:EnumIntEnumFlagIntFlagIt also defines one decorator, unique(), and one helper, auto.它还定义了一个装饰器unique()和一个helperauto

classenum.Enum

Base class for creating enumerated constants. 用于创建枚举常量的基类。See section Functional API for an alternate construction syntax.有关替代构造语法,请参阅Functional API一节。

classenum.IntEnum

Base class for creating enumerated constants that are also subclasses of int.用于创建枚举常量的基类,枚举常量也是int的子类。

classenum.IntFlag

Base class for creating enumerated constants that can be combined using the bitwise operators without losing their IntFlag membership. 用于创建枚举常量的基类,可以使用位运算符组合这些常量,而不会丢失其IntFlag成员身份。IntFlag members are also subclasses of int.成员也是int的子类。

classenum.Flag

Base class for creating enumerated constants that can be combined using the bitwise operations without losing their Flag membership.用于创建枚举常量的基类,该枚举常量可以使用逐位运算进行组合,而不会丢失其Flag成员身份。

enum.unique()

Enum class decorator that ensures only one name is bound to any one value.枚举类装饰器,确保只有一个名称绑定到任何一个值。

classenum.auto

Instances are replaced with an appropriate value for Enum members. 实例将替换为枚举成员的适当值。By default, the initial value starts at 1.默认情况下,初始值从1开始。

New in version 3.6.版本3.6中新增。Flag, IntFlag, auto

Creating an Enum创建枚举

Enumerations are created using the class syntax, which makes them easy to read and write. 枚举是使用class语法创建的,这使得它们易于读写。An alternative creation method is described in Functional API. 函数API中描述了另一种创建方法。To define an enumeration, subclass Enum as follows:要定义枚举,请按如下所示对Enum进行子类化:

>>> from enum import Enum
>>> class Color(Enum):
... RED = 1
... GREEN = 2
... BLUE = 3
...

Note

Enum member values枚举成员值

Member values can be anything: int, str, etc.. 成员值可以是任何值:intstr等……If the exact value is unimportant you may use auto instances and an appropriate value will be chosen for you. 如果精确值不重要,您可以使用auto实例,并为您选择适当的值。Care must be taken if you mix auto with other values.如果将auto与其他值混合,则必须小心。

Note

Nomenclature命名法

  • The class Color is an enumeration (or enum)Colorenumeration(或enum

  • The attributes Color.RED, Color.GREEN, etc., are enumeration members (or enum members) and are functionally constants.Color.REDColor.GREEN等属性是enumeration members(或enum members),是功能常量。

  • The enum members have names and values (the name of Color.RED is RED, the value of Color.BLUE is 3, etc.)枚举成员具有namesvaluesColor.RED的名称为红色,Color.BLUE的值为3,等等)

Note

Even though we use the class syntax to create Enums, Enums are not normal Python classes. 即使我们使用class语法来创建枚举,枚举也不是普通的Python类。See How are Enums different? for more details.看看枚举有什么不同?了解更多详细信息。

Enumeration members have human readable string representations:枚举成员具有可读的字符串表示:

>>> print(Color.RED)
Color.RED

…while their repr has more information:虽然他们的repr有更多信息:

>>> print(repr(Color.RED))
<Color.RED: 1>

The type of an enumeration member is the enumeration it belongs to:枚举成员的type是其所属的枚举:

>>> type(Color.RED)
<enum 'Color'>
>>> isinstance(Color.GREEN, Color)
True
>>>

Enum members also have a property that contains just their item name:枚举成员还有一个仅包含其项名称的属性:

>>> print(Color.RED.name)
RED

Enumerations support iteration, in definition order:枚举支持迭代,按定义顺序:

>>> class Shake(Enum):
... VANILLA = 7
... CHOCOLATE = 4
... COOKIES = 9
... MINT = 3
...
>>> for shake in Shake:
... print(shake)
...
Shake.VANILLA
Shake.CHOCOLATE
Shake.COOKIES
Shake.MINT

Enumeration members are hashable, so they can be used in dictionaries and sets:枚举成员是可散列的,因此可以在字典和集合中使用它们:

>>> apples = {}
>>> apples[Color.RED] = 'red delicious'
>>> apples[Color.GREEN] = 'granny smith'
>>> apples == {Color.RED: 'red delicious', Color.GREEN: 'granny smith'}
True

Programmatic access to enumeration members and their attributes对枚举成员及其属性的编程访问

Sometimes it’s useful to access members in enumerations programmatically (i.e. situations where Color.RED won’t do because the exact color is not known at program-writing time). 有时,以编程方式访问枚举中的成员是有用的(例如,在某些情况下,由于在程序编写时不知道确切的颜色,所以Color.RED不起作用)。Enum allows such access:允许此类访问:

>>> Color(1)
<Color.RED: 1>
>>> Color(3)
<Color.BLUE: 3>

If you want to access enum members by name, use item access:如果要按name访问枚举成员,请使用项访问:

>>> Color['RED']
<Color.RED: 1>
>>> Color['GREEN']
<Color.GREEN: 2>

If you have an enum member and need its name or value:如果您有一个枚举成员并需要其namevalue

>>> member = Color.RED
>>> member.name
'RED'
>>> member.value
1

Duplicating enum members and values复制枚举成员和值

Having two enum members with the same name is invalid:具有两个同名的枚举成员无效:

>>> class Shape(Enum):
... SQUARE = 2
... SQUARE = 3
...
Traceback (most recent call last):
...
TypeError: Attempted to reuse key: 'SQUARE'

However, two enum members are allowed to have the same value. 但是,允许两个枚举成员具有相同的值。Given two members A and B with the same value (and A defined first), B is an alias to A. 给定两个值相同的成员A和B(首先定义A),B是A的别名。By-value lookup of the value of A and B will return A. 按值查找A和B的值将返回A。By-name lookup of B will also return A:按名称查找B也将返回A:

>>> class Shape(Enum):
... SQUARE = 2
... DIAMOND = 1
... CIRCLE = 3
... ALIAS_FOR_SQUARE = 2
...
>>> Shape.SQUARE
<Shape.SQUARE: 2>
>>> Shape.ALIAS_FOR_SQUARE
<Shape.SQUARE: 2>
>>> Shape(2)
<Shape.SQUARE: 2>

Note

Attempting to create a member with the same name as an already defined attribute (another member, a method, etc.) or attempting to create an attribute with the same name as a member is not allowed.不允许尝试创建与已定义属性(另一个成员、方法等)同名的成员或尝试创建与成员同名的属性。

Ensuring unique enumeration values确保枚举值唯一

By default, enumerations allow multiple names as aliases for the same value. 默认情况下,枚举允许多个名称作为同一值的别名。When this behavior isn’t desired, the following decorator can be used to ensure each value is used only once in the enumeration:当不需要此行为时,可以使用以下装饰器来确保每个值在枚举中仅使用一次:

@enum.unique

A class decorator specifically for enumerations. 专门用于枚举的class装饰器。It searches an enumeration’s __members__ gathering any aliases it finds; if any are found ValueError is raised with the details:它搜索枚举的__members__,收集找到的任何别名;如果发现任何值,则会引发错误,并提供详细信息:

>>> 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

Using automatic values使用自动值

If the exact value is unimportant you can use auto:如果精确值不重要,可以使用auto

>>> from enum import Enum, auto
>>> class Color(Enum):
... RED = auto()
... BLUE = auto()
... GREEN = auto()
...
>>> list(Color)
[<Color.RED: 1>, <Color.BLUE: 2>, <Color.GREEN: 3>]

The values are chosen by _generate_next_value_(), which can be overridden:这些值由_generate_next_value_()选择,可以覆盖:

>>> class AutoName(Enum):
... def _generate_next_value_(name, start, count, last_values):
... return name
...
>>> class Ordinal(AutoName):
... NORTH = auto()
... SOUTH = auto()
... EAST = auto()
... WEST = auto()
...
>>> list(Ordinal)
[<Ordinal.NORTH: 'NORTH'>, <Ordinal.SOUTH: 'SOUTH'>, <Ordinal.EAST: 'EAST'>, <Ordinal.WEST: 'WEST'>]

Note

The goal of the default _generate_next_value_() method is to provide the next int in sequence with the last int provided, but the way it does this is an implementation detail and may change.默认的_generate_next_value_()方法的目标是按顺序提供下一个int和提供的最后一个int,但它这样做的方式是一个实现细节,可能会改变。

Note

The _generate_next_value_() method must be defined before any members.必须在任何成员之前定义_generate_next_value()方法。

Iteration迭代

Iterating over the members of an enum does not provide the aliases:迭代枚举的成员不会提供别名:

>>> list(Shape)
[<Shape.SQUARE: 2>, <Shape.DIAMOND: 1>, <Shape.CIRCLE: 3>]

The special attribute __members__ is a read-only ordered mapping of names to members. 特殊属性__members__是名称到成员的只读有序映射。It includes all names defined in the enumeration, including the aliases:它包括枚举中定义的所有名称,包括别名:

>>> for name, member in Shape.__members__.items():
... name, member
...
('SQUARE', <Shape.SQUARE: 2>)
('DIAMOND', <Shape.DIAMOND: 1>)
('CIRCLE', <Shape.CIRCLE: 3>)
('ALIAS_FOR_SQUARE', <Shape.SQUARE: 2>)

The __members__ attribute can be used for detailed programmatic access to the enumeration members. __members__属性可用于对枚举成员进行详细的编程访问。For example, finding all the aliases:例如,查找所有别名:

>>> [name for name, member in Shape.__members__.items() if member.name != name]
['ALIAS_FOR_SQUARE']

Comparisons比较

Enumeration members are compared by identity:枚举成员按身份进行比较:

>>> Color.RED is Color.RED
True
>>> Color.RED is Color.BLUE
False
>>> Color.RED is not Color.BLUE
True

Ordered comparisons between enumeration values are not supported. 不支持枚举值之间的有序比较。Enum members are not integers (but see IntEnum below):枚举成员不是整数(但请参见下面的IntEnum):

>>> Color.RED < Color.BLUE
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'Color' and 'Color'

Equality comparisons are defined though:等式比较的定义如下:

>>> Color.BLUE == Color.RED
False
>>> Color.BLUE != Color.RED
True
>>> Color.BLUE == Color.BLUE
True

Comparisons against non-enumeration values will always compare not equal (again, IntEnum was explicitly designed to behave differently, see below):与非枚举值的比较总是比较不相等(同样,IntEnum被明确设计为具有不同的行为,请参阅下文):

>>> Color.BLUE == 2
False

Allowed members and attributes of enumerations枚举的允许成员和属性

The examples above use integers for enumeration values. 上述示例使用整数作为枚举值。Using integers is short and handy (and provided by default by the Functional API), but not strictly enforced. 使用整数既短又方便(默认情况下由函数API提供),但没有严格执行。In the vast majority of use-cases, one doesn’t care what the actual value of an enumeration is. 在绝大多数用例中,人们并不关心枚举的实际值是多少。But if the value is important, enumerations can have arbitrary values.但是,如果值很重要,枚举可以具有任意值。

Enumerations are Python classes, and can have methods and special methods as usual. 枚举是Python类,通常可以有方法和特殊方法。If we have this enumeration:如果我们有此枚举:

>>> class Mood(Enum):
... FUNKY = 1
... HAPPY = 3
...
... def describe(self):
... # self is the member here
... return self.name, self.value
...
... def __str__(self):
... return 'my custom str! {0}'.format(self.value)
...
... @classmethod
... def favorite_mood(cls):
... # cls here is the enumeration
... return cls.HAPPY
...

Then:然后:

>>> Mood.favorite_mood()
<Mood.HAPPY: 3>
>>> Mood.HAPPY.describe()
('HAPPY', 3)
>>> str(Mood.FUNKY)
'my custom str! 1'

The rules for what is allowed are as follows: names that start and end with a single underscore are reserved by enum and cannot be used; all other attributes defined within an enumeration will become members of this enumeration, with the exception of special methods (__str__(), __add__(), etc.), descriptors (methods are also descriptors), and variable names listed in _ignore_.允许的规则如下:以单下划线开头和结尾的名称由enum保留,不能使用;枚举中定义的所有其他属性都将成为该枚举的成员,但特殊方法(__str__()__add__()等)、描述符(方法也是描述符)和_ignore_中列出的变量名除外。

Note: if your enumeration defines __new__() and/or __init__() then any value(s) given to the enum member will be passed into those methods. 注意:如果枚举定义了__new__()和/或__init__(),则给枚举成员的任何值都将传递给这些方法。See Planet for an example.请参阅Planet以获取示例。

Restricted Enum subclassing受限枚举子类化

A new Enum class must have one base Enum class, up to one concrete data type, and as many object-based mixin classes as needed. 一个新的Enum类必须有一个基本枚举类,最多一个具体的数据类型,以及根据需要的任意多个基于object的混合类。The order of these base classes is:这些基类的顺序是:

class EnumName([mix-in, ...,] [data-type,] base-enum):
pass

Also, subclassing an enumeration is allowed only if the enumeration does not define any members. 此外,仅当枚举未定义任何成员时,才允许对枚举进行子类化。So this is forbidden:所以这是禁止的:

>>> class MoreColor(Color):
... PINK = 17
...
Traceback (most recent call last):
...
TypeError: MoreColor: cannot extend enumeration 'Color'

But this is allowed:但这是允许的:

>>> class Foo(Enum):
... def some_behavior(self):
... pass
...
>>> class Bar(Foo):
... HAPPY = 1
... SAD = 2
...

Allowing subclassing of enums that define members would lead to a violation of some important invariants of types and instances. 允许对定义成员的枚举进行子类化将导致违反类型和实例的一些重要不变量。On the other hand, it makes sense to allow sharing some common behavior between a group of enumerations. 另一方面,允许在一组枚举之间共享一些常见行为是有意义的。(See OrderedEnum for an example.)(有关示例,请参阅OrderedEnum。)

Pickling

Enumerations can be pickled and unpickled:可以对枚举进行pickle和unpickle:

>>> from test.test_enum import Fruit
>>> from pickle import dumps, loads
>>> Fruit.TOMATO is loads(dumps(Fruit.TOMATO))
True

The usual restrictions for pickling apply: picklable enums must be defined in the top level of a module, since unpickling requires them to be importable from that module.pickle的常见限制适用:pickle枚举必须在模块的顶层定义,因为取消pickle要求它们可以从该模块导入。

Note

With pickle protocol version 4 it is possible to easily pickle enums nested in other classes.使用pickle协议版本4,可以轻松地pickle嵌套在其他类中的枚举。

It is possible to modify how Enum members are pickled/unpickled by defining __reduce_ex__() in the enumeration class.可以通过在枚举类中定义__reduce_ex__()来修改枚举成员的pickle/unpickle方式。

Functional API功能API

The Enum class is callable, providing the following functional API:Enum类是可调用的,提供以下功能API:

>>> Animal = Enum('Animal', 'ANT BEE CAT DOG')
>>> Animal
<enum 'Animal'>
>>> Animal.ANT
<Animal.ANT: 1>
>>> Animal.ANT.value
1
>>> list(Animal)
[<Animal.ANT: 1>, <Animal.BEE: 2>, <Animal.CAT: 3>, <Animal.DOG: 4>]

The semantics of this API resemble namedtuple. 这个API的语义类似于namedtupleThe first argument of the call to Enum is the name of the enumeration.调用Enum的第一个参数是枚举的名称。

The second argument is the source of enumeration member names. 第二个参数是枚举成员名称的sourceIt can be a whitespace-separated string of names, a sequence of names, a sequence of 2-tuples with key/value pairs, or a mapping (e.g. dictionary) of names to values. 它可以是以空格分隔的名称字符串、名称序列、具有键/值对的2元组序列,或名称到值的映射(例如字典)。The last two options enable assigning arbitrary values to enumerations; the others auto-assign increasing integers starting with 1 (use the start parameter to specify a different starting value). 最后两个选项允许为枚举指定任意值;其他变量自动分配从1开始的递增整数(使用start参数指定不同的起始值)。A new class derived from Enum is returned. 返回从Enum派生的新类。In other words, the above assignment to Animal is equivalent to:换句话说,上述对Animal的分配相当于:

>>> class Animal(Enum):
... ANT = 1
... BEE = 2
... CAT = 3
... DOG = 4
...

The reason for defaulting to 1 as the starting number and not 0 is that 0 is False in a boolean sense, but enum members all evaluate to True.将起始数默认为1而不是0的原因是0在布尔意义上为False,但枚举成员的计算结果均为True

Pickling enums created with the functional API can be tricky as frame stack implementation details are used to try and figure out which module the enumeration is being created in (e.g. it will fail if you use a utility function in separate module, and also may not work on IronPython or Jython). 使用函数API创建的pickle枚举可能很复杂,因为帧堆栈实现细节用于尝试确定在哪个模块中创建枚举(例如,如果在单独的模块中使用实用程序函数,它将失败,并且可能无法在IronPython或Jython上工作)。The solution is to specify the module name explicitly as follows:解决方案是明确指定模块名称,如下所示:

>>> Animal = Enum('Animal', 'ANT BEE CAT DOG', module=__name__)

Warning

If module is not supplied, and Enum cannot determine what it is, the new Enum members will not be unpicklable; to keep errors closer to the source, pickling will be disabled.如果未提供module,并且Enum无法确定它是什么,则新的Enum成员将不会不可拼接;为了使错误更接近源,将禁用酸洗。

The new pickle protocol 4 also, in some circumstances, relies on __qualname__ being set to the location where pickle will be able to find the class. 在某些情况下,新的pickle协议4还依赖于将__qualname__设置为pickle能够找到类的位置。For example, if the class was made available in class SomeData in the global scope:例如,如果该类在全局范围内的类SomeData中可用:

>>> Animal = Enum('Animal', 'ANT BEE CAT DOG', qualname='SomeData.Animal')

The complete signature is:完整签名为:

Enum(value='NewEnumName', names=<...>, *, module='...', qualname='...', type=<mixed-in class>, start=1)
value

What the new Enum class will record as its name.新枚举类将记录的内容作为其名称。

names姓名

The Enum members. 枚举成员。This can be a whitespace or comma separated string (values will start at 1 unless otherwise specified):这可以是空白或逗号分隔的字符串(除非另有规定,否则值将从1开始):

'RED GREEN BLUE' | 'RED,GREEN,BLUE' | 'RED, GREEN, BLUE'

or an iterator of names:或名称的迭代器:

['RED', 'GREEN', 'BLUE']

or an iterator of (name, value) pairs:或(名称、值)对的迭代器:

[('CYAN', 4), ('MAGENTA', 5), ('YELLOW', 6)]

or a mapping:或映射:

{'CHARTREUSE': 7, 'SEA_GREEN': 11, 'ROSEMARY': 42}
module模块

name of module where new Enum class can be found.可以在其中找到新枚举类的模块的名称。

qualname限定名

where in module new Enum class can be found.在模块中,可以找到新的枚举类。

type类型

type to mix in to new Enum class.键入以混合到新枚举类中。

start

number to start counting at if only names are passed in.如果只传入名称,则开始计数的数字。

Changed in version 3.5:版本3.5中更改: The start parameter was added.添加了start参数。

Derived Enumerations派生枚举

IntEnum

The first variation of Enum that is provided is also a subclass of int. 提供的Enum的第一个变体也是int的一个子类。Members of an IntEnum can be compared to integers; by extension, integer enumerations of different types can also be compared to each other:IntEnum的成员可以与整数进行比较;通过扩展,还可以相互比较不同类型的整数枚举:

>>> from enum import IntEnum
>>> class Shape(IntEnum):
... CIRCLE = 1
... SQUARE = 2
...
>>> class Request(IntEnum):
... POST = 1
... GET = 2
...
>>> Shape == 1
False
>>> Shape.CIRCLE == 1
True
>>> Shape.CIRCLE == Request.POST
True

However, they still can’t be compared to standard Enum enumerations:但是,它们仍然无法与标准Enum枚举进行比较:

>>> class Shape(IntEnum):
... CIRCLE = 1
... SQUARE = 2
...
>>> class Color(Enum):
... RED = 1
... GREEN = 2
...
>>> Shape.CIRCLE == Color.RED
False

IntEnum values behave like integers in other ways you’d expect:值在其他方面与整数类似:

>>> int(Shape.CIRCLE)
1
>>> ['a', 'b', 'c'][Shape.CIRCLE]
'b'
>>> [i for i in range(Shape.SQUARE)]
[0, 1]

IntFlag

The next variation of Enum provided, IntFlag, is also based on int. 提供的Enum的下一个变体IntFlag也基于intThe difference being IntFlag members can be combined using the bitwise operators (&, |, ^, ~) and the result is still an IntFlag member. 可以使用位运算符(&|^~)组合IntFlag成员的差异,结果仍然是IntFlag成员。However, as the name implies, IntFlag members also subclass int and can be used wherever an int is used. 然而,顾名思义,IntFlag成员也是int的子类,可以在使用int的任何地方使用。Any operation on an IntFlag member besides the bit-wise operations will lose the IntFlag membership.除逐位操作外,对IntFlag成员的任何操作都将失去IntFlag成员身份。

New in version 3.6.版本3.6中新增。

Sample IntFlag class:IntFlag类范例:

>>> from enum import IntFlag
>>> class Perm(IntFlag):
... R = 4
... W = 2
... X = 1
...
>>> Perm.R | Perm.W
<Perm.R|W: 6>
>>> Perm.R + Perm.W
6
>>> RW = Perm.R | Perm.W
>>> Perm.R in RW
True

It is also possible to name the combinations:也可以命名这些组合:

>>> class Perm(IntFlag):
... R = 4
... W = 2
... X = 1
... RWX = 7
>>> Perm.RWX
<Perm.RWX: 7>
>>> ~Perm.RWX
<Perm.-8: -8>

Another important difference between IntFlag and Enum is that if no flags are set (the value is 0), its boolean evaluation is False:IntFlagEnum之间的另一个重要区别是,如果未设置任何标志(值为0),则其布尔值为False

>>> Perm.R & Perm.X
<Perm.0: 0>
>>> bool(Perm.R & Perm.X)
False

Because IntFlag members are also subclasses of int they can be combined with them:由于IntFlag成员也是int的子类,因此可以将它们组合在一起:

>>> Perm.X | 8
<Perm.8|X: 9>

Flag

The last variation is Flag. 最后一个变体是FlagLike IntFlag, Flag members can be combined using the bitwise operators (&, |, ^, ~). IntFlag类似,可以使用位运算符(&|^~)组合Flag成员。Unlike IntFlag, they cannot be combined with, nor compared against, any other Flag enumeration, nor int. IntFlag不同,它们不能与任何其他Flag枚举或int组合或进行比较。While it is possible to specify the values directly it is recommended to use auto as the value and let Flag select an appropriate value.虽然可以直接指定值,但建议使用auto作为值,并让Flag选择适当的值。

New in version 3.6.版本3.6中新增。

Like IntFlag, if a combination of Flag members results in no flags being set, the boolean evaluation is False:IntFlag类似,如果Flag成员的组合导致未设置标志,则布尔计算为False

>>> from enum import Flag, auto
>>> class Color(Flag):
... RED = auto()
... BLUE = auto()
... GREEN = auto()
...
>>> Color.RED & Color.GREEN
<Color.0: 0>
>>> bool(Color.RED & Color.GREEN)
False

Individual flags should have values that are powers of two (1, 2, 4, 8, …), while combinations of flags won’t:单个标志的值应为二的幂(1、2、4、8),而标志的组合不会:

>>> class Color(Flag):
... RED = auto()
... BLUE = auto()
... GREEN = auto()
... WHITE = RED | BLUE | GREEN
...
>>> Color.WHITE
<Color.WHITE: 7>

Giving a name to the “no flags set” condition does not change its boolean value:为“未设置标志”条件命名不会更改其布尔值:

>>> class Color(Flag):
... BLACK = 0
... RED = auto()
... BLUE = auto()
... GREEN = auto()
...
>>> Color.BLACK
<Color.BLACK: 0>
>>> bool(Color.BLACK)
False

Note

For the majority of new code, Enum and Flag are strongly recommended, since IntEnum and IntFlag break some semantic promises of an enumeration (by being comparable to integers, and thus by transitivity to other unrelated enumerations). 对于大多数新代码,强烈建议使用EnumFlag,因为IntEnumIntFlag破坏了枚举的一些语义承诺(通过与整数相比较,从而通过传递到其他不相关的枚举)。IntEnum and IntFlag should be used only in cases where Enum and Flag will not do; for example, when integer constants are replaced with enumerations, or for interoperability with other systems.IntEnumIntFlag只能在EnumFlag不起作用的情况下使用;例如,当整数常数被枚举替换时,或者为了与其他系统的互操作性。

Others其他

While IntEnum is part of the enum module, it would be very simple to implement independently:虽然IntEnumenum模块的一部分,但独立实现将非常简单:

class IntEnum(int, Enum):
pass

This demonstrates how similar derived enumerations can be defined; for example a StrEnum that mixes in str instead of int.这说明了如何定义类似的派生枚举;例如,StrEnum混合在str而不是int中。

Some rules:一些规则:

  1. When subclassing Enum, mix-in types must appear before Enum itself in the sequence of bases, as in the IntEnum example above.当对Enum进行子类化时,mix-in类型必须以基序列出现在Enum本身之前,如上面的IntEnum示例所示。

  2. While Enum can have members of any type, once you mix in an additional type, all the members must have values of that type, e.g. int above. 虽然Enum可以有任何类型的成员,但一旦您混合了其他类型,所有成员都必须具有该类型的值,例如上面的intThis restriction does not apply to mix-ins which only add methods and don’t specify another type.此限制不适用于仅添加方法且未指定其他类型的混合插件。

  3. When another data type is mixed in, the value attribute is not the same as the enum member itself, although it is equivalent and will compare equal.当混合了另一种数据类型时,value属性与enum成员本身不同,尽管它是等效的,并且将进行等效比较。

  4. %-style formatting: %s and %r call the Enum class’s __str__() and __repr__() respectively; other codes (such as %i or %h for IntEnum) treat the enum member as its mixed-in type.%-样式格式:%s%r分别调用Enum类的__str__()__repr__();其他代码(例如用于IntEnum的%i%h)将枚举成员视为其混合类型。

  5. Formatted string literals, str.format(), and format() will use the mixed-in type’s __format__() unless __str__() or __format__() is overridden in the subclass, in which case the overridden methods or Enum methods will be used. 格式化字符串文字str.format()format()将使用混合输入类型的__format__()除非在子类中重写了__str__()__format__(),在这种情况下,将使用被重写的方法或枚举方法。Use the !s and !r format codes to force usage of the Enum class’s __str__() and __repr__() methods.使用!s!r格式代码,强制使用Enum类的__str__()方法和__repr__()方法。

When to use __new__() vs. __init__()何时使用__new__()、何时使用__init__()

__new__() must be used whenever you want to customize the actual value of the Enum member. 每当您想要自定义枚举成员的实际值时,都必须使用__new__()命令。Any other modifications may go in either __new__() or __init__(), with __init__() being preferred.任何其他修改可以在__new__()__init__()中进行,首选__init__()

For example, if you want to pass several items to the constructor, but only want one of them to be the value:例如,如果要将多个项传递给构造函数,但只希望其中一个为值:

>>> class Coordinate(bytes, Enum):
... """
... Coordinate with binary codes that can be indexed by the int code.
... """
... def __new__(cls, value, label, unit):
... obj = bytes.__new__(cls, [value])
... obj._value_ = value
... obj.label = label
... obj.unit = unit
... return obj
... PX = (0, 'P.X', 'km')
... PY = (1, 'P.Y', 'km')
... VX = (2, 'V.X', 'km/s')
... VY = (3, 'V.Y', 'km/s')
...
>>> print(Coordinate['PY'])
Coordinate.PY

>>> print(Coordinate(3))
Coordinate.VY

Interesting examples有趣的例子

While Enum, IntEnum, IntFlag, and Flag are expected to cover the majority of use-cases, they cannot cover them all. 虽然EnumIntEnumIntFlagFlag预计将涵盖大多数用例,但它们不能涵盖所有用例。Here are recipes for some different types of enumerations that can be used directly, or as examples for creating one’s own.以下是一些不同类型枚举的配方,可以直接使用,也可以作为创建自己枚举的示例。

Omitting values忽略值

In many use-cases one doesn’t care what the actual value of an enumeration is. 在许多用例中,人们并不关心枚举的实际值是多少。There are several ways to define this type of simple enumeration:有几种方法可以定义这种类型的简单枚举:

  • use instances of auto for the value使用auto实例作为值

  • use instances of object as the value使用object实例作为值

  • use a descriptive string as the value使用描述性字符串作为值

  • use a tuple as the value and a custom __new__() to replace the tuple with an int value使用元组作为值,并使用自定义的__new__()将元组替换为int

Using any of these methods signifies to the user that these values are not important, and also enables one to add, remove, or reorder members without having to renumber the remaining members.使用这些方法中的任何一种都向用户表明这些值并不重要,并且还允许用户添加、删除或重新排序成员,而无需对其余成员重新编号。

Whichever method you choose, you should provide a repr() that also hides the (unimportant) value:无论选择哪种方法,都应该提供一个repr(),它还隐藏(不重要)的值:

>>> class NoValue(Enum):
... def __repr__(self):
... return '<%s.%s>' % (self.__class__.__name__, self.name)
...

Using 使用auto

Using auto would look like:用如下方式使用auto

>>> class Color(NoValue):
... RED = auto()
... BLUE = auto()
... GREEN = auto()
...
>>> Color.GREEN
<Color.GREEN>

Using 使用object

Using object would look like:用如下方式使用object

>>> class Color(NoValue):
... RED = object()
... GREEN = object()
... BLUE = object()
...
>>> Color.GREEN
<Color.GREEN>

Using a descriptive string使用描述性字符串

Using a string as the value would look like:使用字符串作为值如下所示:

>>> class Color(NoValue):
... RED = 'stop'
... GREEN = 'go'
... BLUE = 'too fast!'
...
>>> Color.GREEN
<Color.GREEN>
>>> Color.GREEN.value
'go'

Using a custom 使用自定义__new__()

Using an auto-numbering __new__() would look like:用如下方式使用自动编号__new__()

>>> class AutoNumber(NoValue):
... def __new__(cls):
... value = len(cls.__members__) + 1
... obj = object.__new__(cls)
... obj._value_ = value
... return obj
...
>>> class Color(AutoNumber):
... RED = ()
... GREEN = ()
... BLUE = ()
...
>>> Color.GREEN
<Color.GREEN>
>>> Color.GREEN.value
2

To make a more general purpose AutoNumber, add *args to the signature:要生成更通用的AutoNumber,请在签名中添加*args

>>> class AutoNumber(NoValue):
... def __new__(cls, *args): # this is the only change from above
... value = len(cls.__members__) + 1
... obj = object.__new__(cls)
... obj._value_ = value
... return obj
...

Then when you inherit from AutoNumber you can write your own __init__ to handle any extra arguments:然后,当您从AutoNumber继承时,可以编写自己的__init__来处理任何额外的参数:

>>> class Swatch(AutoNumber):
... def __init__(self, pantone='unknown'):
... self.pantone = pantone
... AUBURN = '3497'
... SEA_GREEN = '1246'
... BLEACHED_CORAL = () # New color, no Pantone code yet!
...
>>> Swatch.SEA_GREEN
<Swatch.SEA_GREEN>
>>> Swatch.SEA_GREEN.pantone
'1246'
>>> Swatch.BLEACHED_CORAL.pantone
'unknown'

Note

The __new__() method, if defined, is used during creation of the Enum members; it is then replaced by Enum’s __new__() which is used after class creation for lookup of existing members.如果定义了__new__()方法,则在创建枚举成员期间使用该方法;然后,它被Enum的__new__()替换,该函数在类创建后用于查找现有成员。

OrderedEnum

An ordered enumeration that is not based on IntEnum and so maintains the normal Enum invariants (such as not being comparable to other enumerations):不基于IntEnum的有序枚举,因此保持正常Enum不变量(例如与其他枚举不可比):

>>> class OrderedEnum(Enum):
... def __ge__(self, other):
... if self.__class__ is other.__class__:
... return self.value >= other.value
... return NotImplemented
... def __gt__(self, other):
... if self.__class__ is other.__class__:
... return self.value > other.value
... return NotImplemented
... def __le__(self, other):
... if self.__class__ is other.__class__:
... return self.value <= other.value
... return NotImplemented
... def __lt__(self, other):
... if self.__class__ is other.__class__:
... return self.value < other.value
... return NotImplemented
...
>>> class Grade(OrderedEnum):
... A = 5
... B = 4
... C = 3
... D = 2
... F = 1
...
>>> Grade.C < Grade.A
True

DuplicateFreeEnum

Raises an error if a duplicate member name is found instead of creating an alias:如果发现重复的成员名称而不是创建别名,则会引发错误:

>>> 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))
...
>>> class Color(DuplicateFreeEnum):
... RED = 1
... GREEN = 2
... BLUE = 3
... GRENE = 2
...
Traceback (most recent call last):
...
ValueError: aliases not allowed in DuplicateFreeEnum: 'GRENE' --> 'GREEN'

Note

This is a useful example for subclassing Enum to add or change other behaviors as well as disallowing aliases. 这是一个很有用的例子,可以对Enum进行子类化,以添加或更改其他行为以及禁止别名。If the only desired change is disallowing aliases, the unique() decorator can be used instead.如果唯一需要的更改是不允许别名,则可以使用unique()修饰符。

Planet

If __new__() or __init__() is defined the value of the enum member will be passed to those methods:如果定义了__new__()__init__(),枚举成员的值将传递给这些方法:

>>> class Planet(Enum):
... MERCURY = (3.303e+23, 2.4397e6)
... VENUS = (4.869e+24, 6.0518e6)
... EARTH = (5.976e+24, 6.37814e6)
... MARS = (6.421e+23, 3.3972e6)
... JUPITER = (1.9e+27, 7.1492e7)
... SATURN = (5.688e+26, 6.0268e7)
... URANUS = (8.686e+25, 2.5559e7)
... NEPTUNE = (1.024e+26, 2.4746e7)
... def __init__(self, mass, radius):
... self.mass = mass # in kilograms
... self.radius = radius # in meters
... @property
... def surface_gravity(self):
... # universal gravitational constant (m3 kg-1 s-2)
... G = 6.67300E-11
... return G * self.mass / (self.radius * self.radius)
...
>>> Planet.EARTH.value
(5.976e+24, 6378140.0)
>>> Planet.EARTH.surface_gravity
9.802652743337129

TimePeriod

An example to show the _ignore_ attribute in use:显示正在使用的_ignore_属性的示例:

>>> from datetime import timedelta
>>> class Period(timedelta, Enum):
... "different lengths of time"
... _ignore_ = 'Period i'
... Period = vars()
... for i in range(367):
... Period['day_%d' % i] = i
...
>>> list(Period)[:2]
[<Period.day_0: datetime.timedelta(0)>, <Period.day_1: datetime.timedelta(days=1)>]
>>> list(Period)[-2:]
[<Period.day_365: datetime.timedelta(days=365)>, <Period.day_366: datetime.timedelta(days=366)>]

How are Enums different?枚举有什么不同?

Enums have a custom metaclass that affects many aspects of both derived Enum classes and their instances (members).枚举有一个自定义元类,它影响派生枚举类及其实例(成员)的许多方面。

Enum Classes

The EnumMeta metaclass is responsible for providing the __contains__(), __dir__(), __iter__() and other methods that allow one to do things with an Enum class that fail on a typical class, such as list(Color) or some_enum_var in Color. EnumMeta元类负责提供__contains__()__dir__()__iter__()和其他方法,这些方法允许对典型类上失败的枚举类执行操作,例如list(Color)some_enum_var in ColorEnumMeta is responsible for ensuring that various other methods on the final Enum class are correct (such as __new__(), __getnewargs__(), __str__() and __repr__()).EnumMeta负责确保最终枚举类上的各种其他方法是正确的(例如__new__()__getnewargs__()__str__()__repr__()

Enum Members (aka instances)枚举成员(也称为实例)

The most interesting thing about Enum members is that they are singletons. Enum成员最有趣的一点是,它们是单例的。EnumMeta creates them all while it is creating the Enum class itself, and then puts a custom __new__() in place to ensure that no new ones are ever instantiated by returning only the existing member instances.EnumMeta在创建Enum类本身的同时创建它们,然后放置一个自定义的__new__()以确保通过仅返回现有成员实例来实例化任何新实例。

Finer Points更精细的点

Supported __dunder__ names支持的__dunder__名称

__members__ is a read-only ordered mapping of member_name:member items. __members__member_name:member项的只读有序映射。It is only available on the class.它只在类上可用。

__new__(), if specified, must create and return the enum members; it is also a very good idea to set the member’s _value_ appropriately. __new__()如果指定,则必须创建并返回枚举成员;适当地设置成员的_value_也是一个很好的主意。Once all the members are created it is no longer used.创建所有成员后,将不再使用。

Supported _sunder_ names支持的_sunder_名称

  • _name_name of the member成员姓名

  • _value_value of the member; can be set / modified in __new__成员的值;可以在__new__中设置/修改

  • _missing_a lookup function used when a value is not found; may be overridden未找到值时使用的查找函数;可能被覆盖

  • _ignore_a list of names, either as a list or a str, that will not be transformed into members, and will be removed from the final class名称列表,作为liststr,不会转换为成员,并将从最终类中删除

  • _order_used in Python 2/3 code to ensure member order is consistent (class attribute, removed during class creation)在Python 2/3代码中使用,以确保成员顺序一致(类属性,在创建类时删除)

  • _generate_next_value_used by the Functional API and by auto to get an appropriate value for an enum member; may be overridden函数APIauto用于获取枚举成员的适当值;可能被覆盖

New in version 3.6.版本3.6中新增。_missing_, _order_, _generate_next_value__missing__order__generate_next_value_

New in version 3.7.版本3.7中新增。_ignore_

To help keep Python 2 / Python 3 code in sync an _order_ attribute can be provided. 为了帮助保持Python 2/Python 3代码的同步,可以提供一个_order_属性。It will be checked against the actual order of the enumeration and raise an error if the two do not match:将对照枚举的实际顺序进行检查,如果两者不匹配,则会引发错误:

>>> class Color(Enum):
... _order_ = 'RED GREEN BLUE'
... RED = 1
... BLUE = 3
... GREEN = 2
...
Traceback (most recent call last):
...
TypeError: member order does not match _order_

Note

In Python 2 code the _order_ attribute is necessary as definition order is lost before it can be recorded.在Python 2代码中,_order_属性是必需的,因为定义顺序在可以记录之前丢失。

_Private__names

Private names will be normal attributes in Python 3.11 instead of either an error or a member (depending on if the name ends with an underscore). 私有名称将是Python 3.11中的常规属性,而不是错误或成员(取决于名称是否以下划线结尾)。Using these names in 3.10 will issue a DeprecationWarning.在3.10中使用这些名称将发出DeprecationWarning

Enum member type成员类型

Enum members are instances of their Enum class, and are normally accessed as EnumClass.member. Enum成员是其Enum类的实例,通常作为EnumClass.member访问。Under certain circumstances they can also be accessed as EnumClass.member.member, but you should never do this as that lookup may fail or, worse, return something besides the Enum member you are looking for (this is another good reason to use all-uppercase names for members):在某些情况下,它们也可以作为EnumClass.member.member进行访问,但您永远不应该这样做,因为查找可能会失败,或者更糟糕的是,返回您正在查找的Enum成员之外的内容(这是为成员使用所有大写名称的另一个很好的原因):

>>> class FieldTypes(Enum):
... name = 0
... value = 1
... size = 2
...
>>> FieldTypes.value.size
<FieldTypes.size: 2>
>>> FieldTypes.size.value
2

Note

This behavior is deprecated and will be removed in 3.11.此行为已弃用,将在3.11中删除。

Changed in version 3.5.在版本3.5中更改。

Boolean value of Enum classes and membersEnum类和成员的布尔值

Enum members that are mixed with non-Enum types (such as int, str, etc.) are evaluated according to the mixed-in type’s rules; otherwise, all members evaluate as True. 与非Enum类型(如intstr等)混合的Enum成员根据混合类型的规则进行评估;否则,所有成员的评估结果均为TrueTo make your own Enum’s boolean evaluation depend on the member’s value add the following to your class:要使自己的枚举的布尔计算取决于成员的值,请将以下内容添加到类中:

def __bool__(self):
return bool(self.value)

Enum classes always evaluate as True.类始终评估为True

Enum classes with methods具有方法的Enum

If you give your Enum subclass extra methods, like the Planet class above, those methods will show up in a dir() of the member, but not of the class:如果给Enum子类额外的方法,如上面的Planet类,这些方法将显示在成员的dir()中,但不会显示在类的dir()中:

>>> dir(Planet)
['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__']
>>> dir(Planet.EARTH)
['__class__', '__doc__', '__module__', 'mass', 'name', 'radius', 'surface_gravity', 'value']

Combining members of Flag合并Flag成员

If a combination of Flag members is not named, the repr() will include all named flags and all named combinations of flags that are in the value:如果未命名标志成员的组合,repr()将包括所有命名标志和值中的所有命名标志组合:

>>> class Color(Flag):
... RED = auto()
... GREEN = auto()
... BLUE = auto()
... MAGENTA = RED | BLUE
... YELLOW = RED | GREEN
... CYAN = GREEN | BLUE
...
>>> Color(3) # named combination
<Color.YELLOW: 3>
>>> Color(7) # not named combination
<Color.CYAN|MAGENTA|BLUE|YELLOW|GREEN|RED: 7>

Note

In 3.11 unnamed combinations of flags will only produce the canonical flag members (aka single-value flags). 在3.11中,未命名的标志组合将仅产生规范标志成员(也称为单值标志)。So Color(7) will produce something like <Color.BLUE|GREEN|RED: 7>.所以Color(7)会产生类似于<Color.BLUE|GREEN|RED: 7>的东西。