enum
— Support 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
. Enum
、IntEnum
、Flag
和IntFlag
。It also defines one decorator, 它还定义了一个装饰器unique()
, and one helper, auto
.unique()
和一个helperauto
。
-
class
enum.
Enum
¶ Base class for creating enumerated constants.用于创建枚举常量的基类。See section Functional API for an alternate construction syntax.有关替代构造语法,请参阅Functional API一节。
-
class
enum.
IntEnum
¶ Base class for creating enumerated constants that are also subclasses of用于创建枚举常量的基类,枚举常量也是int
.int
的子类。
-
class
enum.
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
的子类。
-
class
enum.
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.枚举类装饰器,确保只有一个名称绑定到任何一个值。
-
class
enum.
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.. int
、str
等……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)Color
是enumeration(或enum)The attributesColor.RED
,Color.GREEN
, etc., are enumeration members (or enum members) and are functionally constants.Color.RED
、Color.GREEN
等属性是enumeration members(或enum members),是功能常量。The enum members have names and values (the name of枚举成员具有names和values(Color.RED
isRED
, the value ofColor.BLUE
is3
, etc.)Color.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
:name
或value
:
>>> 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 (允许的规则如下:以单下划线开头和结尾的名称由enum保留,不能使用;枚举中定义的所有其他属性都将成为该枚举的成员,但特殊方法(__str__()
, __add__()
, etc.), descriptors (methods are also descriptors), and variable names listed in _ignore_
.__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 这个API的语义类似于namedtuple
. namedtuple
。The first argument of the call to 调用Enum
is the name of the enumeration.Enum
的第一个参数是枚举的名称。
The second argument is the source of enumeration member names. 第二个参数是枚举成员名称的source。It 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 最后两个选项允许为枚举指定任意值;其他变量自动分配从1开始的递增整数(使用start
parameter to specify a different starting value). 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 在某些情况下,新的pickle协议4还依赖于将__qualname__
being set to the location where pickle will be able to find the class. __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
也基于int
。The 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
:IntFlag
和Enum
之间的另一个重要区别是,如果未设置任何标志(值为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
. Flag
。Like 与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). Enum
和Flag
,因为IntEnum
和IntFlag
破坏了枚举的一些语义承诺(通过与整数相比较,从而通过传递到其他不相关的枚举)。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.IntEnum
和IntFlag
只能在Enum
和Flag
不起作用的情况下使用;例如,当整数常数被枚举替换时,或者为了与其他系统的互操作性。
Others其他¶
While 虽然IntEnum
is part of the enum
module, it would be very simple to implement independently:IntEnum
是enum
模块的一部分,但独立实现将非常简单:
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:一些规则:
When subclassing当对Enum
, mix-in types must appear beforeEnum
itself in the sequence of bases, as in theIntEnum
example above.Enum
进行子类化时,mix-in类型必须以基序列出现在Enum
本身之前,如上面的IntEnum
示例所示。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
可以有任何类型的成员,但一旦您混合了其他类型,所有成员都必须具有该类型的值,例如上面的int
。This restriction does not apply to mix-ins which only add methods and don’t specify another type.此限制不适用于仅添加方法且未指定其他类型的混合插件。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成员本身不同,尽管它是等效的,并且将进行等效比较。%-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
)将枚举成员视为其混合类型。Formatted string literals,格式化字符串文字、str.format()
, andformat()
will use the mixed-in type’s__format__()
unless__str__()
or__format__()
is overridden in the subclass, in which case the overridden methods orEnum
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__()
vs. __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. Enum
、IntEnum
、IntFlag
和Flag
预计将涵盖大多数用例,但它们不能涵盖所有用例。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 a descriptive string as the value使用描述性字符串作为值use a tuple as the value and a custom使用元组作为值,并使用自定义的__new__()
to replace the tuple with anint
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'
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 Color
。EnumMeta
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__
名称¶
__dunder__
names__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_
名称¶
_sunder_
names_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 astr
, that will not be transformed into members, and will be removed from the final classlist
或str
,不会转换为成员,并将从最终类中删除_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由函数API和auto
to get an appropriate value for an enum member; may be overriddenauto
用于获取枚举成员的适当值;可能被覆盖
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 为了帮助保持Python 2/Python 3代码的同步,可以提供一个_order_
attribute can be provided. _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 在Python 2代码中,_order_
attribute is necessary as definition order is lost before it can be recorded._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 在3.10中使用这些名称将发出DeprecationWarning
.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
classes and members与非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
类型(如int
、str
等)混合的Enum
成员根据混合类型的规则进行评估;否则,所有成员的评估结果均为True
。To 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 with methods具有方法的Enum
类¶
Enum
classes with methodsIf 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
成员¶
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>
的东西。