Python Module之enum-枚举类型
2018-01-03 15:15
323 查看
enum模块可以定义具有迭代和比较能力的枚举类型。它可以为各个值创建具有明确意义的符号标记,而不是使用整数或者字符串。
创建枚举类型
一个新的枚举类型使用类语法,通过继承Enum类,并且在类中添加类属性来描述各个值。
# enum_create.py import enum class BugStatus(enum.Enum): new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 print('\nMember name: {}'.format(BugStatus.wont_fix.name)) print('Member value: {}'.format(BugStatus.wont_fix.value))
Enum的各个成员被转换成实例。每一个实例具有一个
name属性,即我们定义的属性名称,还具有一个
value属性,即我们给属性赋的值。
$ python3 enum_create.py Member name: wont_fix Member value: 4
迭代
枚举类的迭代可以产生每一个单独的枚举变量。# enum_iterate.py import enum class BugStatus(enum.Enum): new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 for status in BugStatus: print('{:15} = {}'.format(status.name, status.value))
成员产生的顺序与它们在类中声明的顺序一致。
name和
value的值并不会影响这个顺序。
$ python3 enum_iterate.py new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1
比较枚举变量
因为枚举类的成员并没有顺序,所以他们只支持对象身份比较和相等比较。# enum_comparison.py import enum class BugStatus(enum.Enum): new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_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('Ordered by value:') try: print('\n'.join(' ' + s.name for s in sorted(BugStatus))) except TypeError as err: print(' Cannot sort: {}'.format(err))
大于和小于的比较将会引发
TypeError异常。
$ python3 enum_comparison.py Equality: False True Identity: False True Ordered by value: Cannot sort: unorderable types: BugStatus() < BugStatus()
使用
IntEnum类将会让枚举类型的成员表现得更像数字类型,比如,他们支持排序。
# enum_intenum.py import enum class BugStatus(enum.IntEnum): new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 print('Ordered by value:') print('\n'.join(' ' + s.name for s in sorted(BugStatus)))
$ python3 enum_intenum.py Ordered by value: fix_released fix_committed in_progress wont_fix invalid incomplete new
唯一的枚举值
具有相同值的枚举成员被看做是同一个对象的不同别名引用。别名也不会引起枚举类的迭代器出现重复值。# enum_aliases.py import enum class BugStatus(enum.Enum): new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 by_design = 4 closed = 1 for 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是另外一些成员的别名,所以它们在我们迭代这个枚举类的时候并不会出现。成员的名字被认为是第一个关联到这个值的名字。
$ python3 enum_aliases.py new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 Same: by_design is wont_fix: True Same: closed is fix_released: True
如果我们需要枚举成员具有唯一的值,可以给枚举类
添加@unique`装饰器。
# enum_unique_enforce.py import enum @enum.unique class BugStatus(enum.Enum): new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 # This will trigger an error with unique applied. by_design = 4 closed = 1
当枚举类被解释执行的时候,如果成员具有重复的值,将会引发
ValueError异常。
$ python3 enum_unique_enforce.py Traceback (most recent call last): File "enum_unique_enforce.py", line 11, in <module> class BugStatus(enum.Enum): File ".../lib/python3.5/enum.py", line 573, in unique (enumeration, alias_details)) ValueError: duplicate values found in <enum 'BugStatus'>: by_design -> wont_fix, closed -> fix_released
程序化创建枚举类
在一些情况下,通过程序化创建枚举类比将它们硬编码到一个类中更加方便。在这些场景中,枚举类允许将成员名字和对应的值传递给类的构造方法。# enum_programmatic_create.py import enum BugStatus = 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开始,自动给每个成员分配一个值。
$ python3 enum_programmatic_create.py Member: BugStatus.new All members: fix_released = 1 fix_committed = 2 in_progress = 3 wont_fix = 4 invalid = 5 incomplete = 6 new = 7
想要对名字和值进行更多的控制,可以给
names传递一个包含两个元素的元组的序列或者一个字典。
# enum_programmatic_mapping.py import enum BugStatus = 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))
在这个例子中,我们给
names参数传递了一个包含两个元素的元组的列表,而不是一个只包含成员名字的字符串。这样我们就可以通过这种方式创建出和
enum_create.py中顺序一样的枚举类。
$ python3 enum_programmatic_mapping.py All members: new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1
非整数成员值
枚举成员值并没有严格限制为整数。实际上,枚举成员可以是任意类型的值。如果值是一个元组,那么成员会作为私有变量传递给__init__()方法。
# enum_tuple_values.py import enum class 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 = num self.transitions = transitions def can_transition(self, new_state): return new_state.name in self.transitions print('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))
在这个例子中,每一成员值都一个元组,包含一个数字ID号和一个当前状态可以转换到的状态列表。
$ python3 enum_tuple_values.py Name: BugStatus.in_progress Value: (3, ['new', 'fix_committed']) Custom attribute: ['new', 'fix_committed'] Using attribute: True
对于更复杂的情况,使用元组变得有些笨拙。因为成员值可以是任意类型的对象,所以我们可以使用字典来标识每个成员值中分散的属性。复杂的成员值作为除
self参数外唯一的参数直接传递给
__init__()方法。
# enum_complex_values.py import enum class 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.transitions print('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))
该示例使用字典而不是元组,但是与上个示例有相同的输出。
$ python3 enum_complex_values.py Name: BugStatus.in_progress Value: {'transitions': ['new', 'fix_committed'], 'num': 3} Custom attribute: ['new', 'fix_committed'] Using attribute: True
原文点这里
参考:
1.enum模块的官方文档
2.PEP 435 - 向Python标准库中添加枚举类型。
3.flufl.enum -
enum最初的灵感来源 by Barry Warsaw
相关文章推荐
- python里使用enum库创建枚举类型
- Python_import Vs from module import
- 枚举类型enum
- PAMIE的全称是Python Automated Module For Internet Explorer,顾名思义,PAMIE是一个实现IE自动化的模块
- python的卸载方式和运行yum报错:No module named yum
- C语言--enum,typedef enum 枚举类型详解
- 升级Python2.7后 no module name yum
- Python配置matplotlib--no module named six matplotlib
- Unable to use IEC module under PortablePython_1.1_py2.5.4
- 【linux C语言开发】有关enum枚举类型的一个测试程序
- python 模块(module)基础讲解
- Java枚举类型enum
- python app.urls. Module not found
- Windows下运行python脚本报错“ImportError: No Module named ...”的解决方法
- Windows cmd下运行python脚本报错“ImportError: No Module named ...”的解决方法
- mac python3.* ModuleNotFoundError: No module named 'MySQLdb'
- PythonHandler trac.web.modpython_frontend: ImportError: No module named trac
- enum枚举类型的使用
- enum枚举类型的定义
- C++11特性(9):强枚举类型enum