Bootstrap

python 枚举(enum)

1. 枚举模块 enum

python 的枚举是使用类来实现的,类属性是枚举名称,属性值对应枚举值。Enum 的使用有如下特点:
枚举类不允许定义相同枚举名称,但不同的枚举名称可以有相同的值,后者相当于前者的别名。
枚举值不能被修改,枚举值一旦被修改,就会引发 AttributeError 异常。
两个不同的枚举类,枚举名称和枚举值即便相同,在比较时也是不相等的。
枚举类的一个枚举有 name(标签)和 value(枚举值)两个属性,使用枚举值时,务必通过 value 获取枚举值。

2. 枚举使用实例

python3 提供了 enum 模块,定义类时继承 enum.Enum,可以创建一个枚举类型数据,除此以外还可以继承 enum.IntEnum,枚举值只能是int。

import enum

class ColorCode(enum.Enum):
    RED = 1
    BLUE = 2
    BLACK = 3

def print_color(color_code):
    if color_code == ColorCode.RED.value:
        print('红色')
    elif color_code == ColorCode.BLUE.value:
        print('蓝色')
    elif color_code == ColorCode.BLACK.value:
        print('黑色')

print_color(1)

枚举值不能被修改,是使用枚举类型进行编程的最重要的目的之一,假设枚举值可以被修改,那么也就没有必要提供 enum 这个模块了,我们使用自定义类和类属性就能够替代 enum 模块。
如果执行:

ColorCode.RED = 4

将会引发错误

raise AttributeError('Cannot reassign members.')
AttributeError: Cannot reassign members.

3. 枚举值

3.1. 枚举值唯一

枚举值理论上是允许重复的,如果不希望出现枚举值重复的情况,可以使用 enum 模块提供的 unique 装饰器

import enum
from enum import unique

@unique
class ColorCode(enum.Enum):
    RED = 1
    BLUE = 1
    BLACK = 3

如果枚举值出现了重复的情况,由于有 unique 装饰器修饰,在执行时会报错。

3.2. 枚举值遍历

使用 for 循环可以对枚举值进行遍历,枚举有 name 和 value 两个属性,name 就是枚举类的类属性,value 则是类属性的值。

import enum
from enum import unique

@unique
class ColorCode(enum.Enum):
    RED = 1
    BLUE = 2
    BLACK = 3

for color in ColorCode:
    print(color.name, color.value)

程序输出结果:

RED 1
BLUE 2
BLACK 3

3.3. 枚举值比较

两个枚举值之间只支持身份运算符 is 和比较运算符 == 进行比较。

print(ColorCode.RED == ColorCode.RED)       # True

这看起来没有什么特别,但如果使用枚举和对应的值进行比较,就会产生一些出乎意料的结果

print(ColorCode.RED == 1)       			# False

这是非常容易出错的地方,很多人相当然的认为 ColorCode.RED 与 1 是相等的,但真实的结果却是 False,RED 是一项枚举,枚举有name 和 value 两个属性,必须通过 value 才能获得真实的枚举值

print(ColorCode.RED.value == 1)       		# True

或者换一个思路,将枚举值转成枚举类型

print(ColorCode.RED == ColorCode(1))       # True

3.4. 是否属于枚举

print(2 in {item.value for item in Color})	# True

4. 实例

from enum import Enum
 
# 定义一个枚举类型
class Color(Enum):
    RED     = 1
    GREEN   = 2
    BLUE    = 3
 
# # 要判断的值
# value_to_check = 2
 
# # 判断值是否在枚举的有效范围内
# is_in_enum_range = value_to_check in Color.__members__
 
# print(is_in_enum_range)  			# 输出: False
print(Color.__members__.keys())		# dict_keys(['RED', 'GREEN', 'BLUE'])
print(Color.__members__.values())	# dict_values([<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 3>])
;