enum模块定义了一个具有迭代和比较能力的枚举类型。它可以用来创建定义良好的数值符号,而不是使用整数或字符串。
Creating Enumerations
定义一个类,通过继承enum.Enum并且添加相关属性描述枚举值
import enumclass BugStatus(enum.Enum):new = 7incomplete = 6invalid = 5wont_fix = 4in_progress = 3fix_committed = 2fix_released = 1
print("Member name:{}".format(BugStatus.wont_fix.name)) # Member name:wont_fix
print("Member value:{}".format(BugStatus.wont_fix.value)) # Member value: 4
Enum的成员在类被解析时被转换为实例。每个实例都有一个对应于成员名称的name属性和与之对应的值value属性。
Iteration
在枚举类上迭代产生枚举的各个成员。
for status in BugStatus:print('{:15} = {}'.format(status.name,status.value))
''' new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 '''
成员是按照类定义中声明的顺序产生的。名称和值不用于以任何方式对它们进行排序。
Comparing Enums
因为枚举成员不是有序的,所以只支持通过is和==进行比较。即不能使用>、小于和其他比较操作。
import enumclass BugStatus(enum.Enum):new = 7incomplete = 6invalid = 5wont_fix = 4in_progress = 3fix_committed = 2fix_released = 1
actual_state = BugStatus.wont_fix
desired_state = BugStatus.fix_released
print('Equality:',actual_state == desired_state,actual_state == BugStatus.wont_fix)
print('Identity:',actual_state is desired_state,actual_state is BugStatus.wont_fix)
print('Orderd by value:')
try:print('\n'.join(' '+s.name for s in sorted(BugStatus)))
except TypeError as err:print('Cannot sort: {}'.format(err))
这里大于和小于比较运算符会触发TypeError错误
Equality: False True
Identity: False True
Ordered by value:
Cannot sort: '<' not supported between instances of 'BugStatus
' and 'BugStatus'
想要枚举成员的行为更像数字的话,例如支持比较运算,可以选择IntEnum类
import enum
class BugStatus(enum.IntEnum):new = 7incomplete = 6invalid = 5wont_fix = 4in_progress = 3fix_committed = 2fix_released = 1
print('Ordered by value:')
print('\n'.join(' ' + s.name for s in sorted(BugStatus)))
Ordered by value:fix_releasedfix_committedin_progresswont_fixinvalidincompletenew
Unique Enumeration Values
具有相同值的Enum成员被跟踪为对同一成员对象的别名引用。别名不会导致Enum的迭代器中出现重复的值。
import enumclass BugStatus(enum.Enum):new = 7incomplete = 6invalid = 5wont_fix = 4in_progress = 3fix_committed = 2fix_released = 1by_design = 4closed = 1for status in BugStatus:print('{:15} = {}'.format(status.name, status.value))print('\nSame: by_design is wont_fix: ',BugStatus.by_design is BugStatus.wont_fix)
print('Same: closed is fix_released: ',BugStatus.closed is BugStatus.fix_released)
因为by_design和closed是其他成员的别名,所以在迭代Enum的时候,它们不会输出。输出成员的名称是附加在值上的第一个名称。
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1Same: by_design is wont_fix: True
Same: closed is fix_released: True
要使的所有成员都是唯一的值,可以添加Enum@unique装饰器。
import enum@enum.unique
class BugStatus(enum.Enum):new = 7incomplete = 6invalid = 5wont_fix = 4in_progress = 3fix_committed = 2fix_released = 1# This will trigger an error with unique applied.by_design = 4closed = 1
这个时候当Enum类被解释时,具有重复值的成员会触发一个ValueError异常。
Traceback (most recent call last):File "enum_unique_enforce.py", line 11, in <module>class BugStatus(enum.Enum):File ".../lib/python3.7/enum.py", line 848, in unique(enumeration, alias_details))
ValueError: duplicate values found in <enum 'BugStatus'>:
by_design -> wont_fix, closed -> fix_released
Creating Enumerations Programmatically
在某些情况下,以programmatically方式创建枚举比在单独在类中定义中更方便。对于这些情况,Enum也支持将成员名和值传递给类构造函数。
enum_programmatic_create.py
import enumBugStatus = enum.Enum(value='BugStatus',names=('fix_released fix_committed in_progress ''wont_fix invalid incomplete new'),
)print('Member: {}'.format(BugStatus.new))print('\nAll members:')
for status in BugStatus:print('{:15} = {}'.format(status.name, status.value))
value参数是枚举的名称,它用于构建成员的表示。names参数列出了枚举的成员。当传递一个单一字符串时,它被分割为空格和逗号,所产生的标记被用作成员的名称,这些成员的值从1开始自动分配。
Member: BugStatus.newAll members:
fix_released = 1
fix_committed = 2
in_progress = 3
wont_fix = 4
invalid = 5
incomplete = 6
new = 7
为了对与成员相关的值进行更多的控制,名字字符串可以用一个两元素的元组或一个将name映射到value的字典来代替。
import enumBugStatus = enum.Enum(value='BugStatus',names=[('new', 7),('incomplete', 6),('invalid', 5),('wont_fix', 4),('in_progress', 3),('fix_committed', 2),('fix_released', 1),],
)print('All members:')
for status in BugStatus:print('{:15} = {}'.format(status.name, status.value))
All members:
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1
枚举成员的value不仅限于整数,任何类型的对象都可以与成员相关联。如果值是一个元组,成员会作为单独的参数传递给 init() 。
import enumclass BugStatus(enum.Enum):new = (7, ['incomplete','invalid','wont_fix','in_progress'])incomplete = (6, ['new', 'wont_fix'])invalid = (5, ['new'])wont_fix = (4, ['new'])in_progress = (3, ['new', 'fix_committed'])fix_committed = (2, ['in_progress', 'fix_released'])fix_released = (1, ['new'])def __init__(self, num, transitions):self.num = numself.transitions = transitionsdef can_transition(self, new_state):return new_state.name in self.transitionsprint('Name:', BugStatus.in_progress)
print('Value:', BugStatus.in_progress.value)
print('Custom attribute:', BugStatus.in_progress.transitions)
print('Using attribute:',BugStatus.in_progress.can_transition(BugStatus.new))
Name: BugStatus.in_progress
Value: (3, ['new', 'fix_committed'])
Custom attribute: ['new', 'fix_committed']
Using attribute: True
对于更复杂的情况,元组可能会变得笨重。因为value可以是任何类型的对象,所以字典可以用于对每个枚举值有很多独立属性需要跟踪的情况。复杂的值作为 self 以外的唯一参数直接传递给 init() 。
import enumclass BugStatus(enum.Enum):new = {
'num': 7,'transitions': ['incomplete','invalid','wont_fix','in_progress',],}incomplete = {
'num': 6,'transitions': ['new', 'wont_fix'],}invalid = {
'num': 5,'transitions': ['new'],}wont_fix = {
'num': 4,'transitions': ['new'],}in_progress = {
'num': 3,'transitions': ['new', 'fix_committed'],}fix_committed = {
'num': 2,'transitions': ['in_progress', 'fix_released'],}fix_released = {
'num': 1,'transitions': ['new'],}def __init__(self, vals):self.num = vals['num']self.transitions = vals['transitions']def can_transition(self, new_state):return new_state.name in self.transitionsprint('Name:', BugStatus.in_progress)
print('Value:', BugStatus.in_progress.value)
print('Custom attribute:', BugStatus.in_progress.transitions)
print('Using attribute:',BugStatus.in_progress.can_transition(BugStatus.new))
Name: BugStatus.in_progress
Value: {
'num': 3, 'transitions': ['new', 'fix_committed']}
Custom attribute: ['new', 'fix_committed']
Using attribute: True
这个例子与前面的例子表达了相同的数据,使用字典而不是元组。