从python 3.x开始提供了 enum
模块来提供枚举的功能,在使用时通过 from enum import Enum
来引入。
开发人员需要自己定义一个继承 Enum
的类来实现枚举类型对象。
python的枚举是使用类来实现的,类属性是枚举名称,属性值对应枚举值。Enum
的使用有如下特点:
枚举类不允许定义相同枚举名称,但不同的枚举名称可以有相同的值,后者相当于前者的别名。
枚举值不能被修改,枚举值一旦被修改,就会引发 AttributeError
异常。
两个不同的枚举类,枚举名称和枚举值即便相同,在比较时也是不相等的。
枚举类的一个枚举有 name
(标签)和 value
(枚举值)两个属性,使用枚举值时,务必通过 value
获取枚举值。
枚举应用场景
枚举有什么作用呢?当一个变量有几种固定的取值时,通常喜欢将它定义为枚举类型, 枚举类型用于声明一组命名的常数,使用枚举类型可以增强代买的可读性。
假设有这样一个函数:
def print_color(color_code):
if color_code == 1:
print('红色')
elif color_code == 2:
print('蓝色')
elif color_code == 3:
print('黑色')
参数 color_code
取值有3种,1表示红色,2表示蓝色,3表示黑色。color_code
是表示颜色的代码,
只有3种取值,这种情形下就适合使用枚举类型来表示,在python没有枚举类型之前,可以使用类来定义枚举类型。
class ColorCode:
RED = 1
BLUE = 2
BLACK = 3
def print_color(color_code):
if color_code == ColorCode.RED:
print('红色')
elif color_code == ColorCode.BLUE:
print('蓝色')
elif color_code == ColorCode.BLACK:
print('黑色')
print_color(1)
红色
函数里不再用 color_code
和1,2,3这些整数值进行比较,而是与 ColorCode
的类属性进行比较,代码可阅读性更好,
因为只看1,2,3,你无法理解这些数字所代表的含义。虽然使用类可以模拟枚举类型,但这种技术有一个缺点,类属性可以随意修改。
ColorCode.RED = 4
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)
红色
看上去和第2小节里的代码没有什么大的区别,但由于继承了 enum.Enum
,
ColorCode
的类属性将无法修改,如果执行:
# ColorCode.RED = 4 #此代码会报错
将会引发错误
raise AttributeError('Cannot reassign members.')
AttributeError: Cannot reassign members.
枚举值不能被修改,是使用枚举类型进行编程的最重要的目的之一,假设枚举值可以被修改,
那么也就没有必要提供 enum
这个模块了,使用自定义类和类属性就能够替代 enum
模块。
# import enum
# from enum import unique
# @unique #此代码会报错
# class ColorCode(enum.Enum):
# RED = 1
# BLUE = 1
# BLACK = 3
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
程序输出结果
RED 1
BLUE 2
BLACK 3
print(ColorCode.RED == ColorCode.RED) # True
True
这看起来没有什么特别,但如果使用枚举和对应的值进行比较,就会产生一些出乎意料的结果。
print(ColorCode.RED == 1) # False
False
这是非常容易出错的地方,很多人相当然的认为 ColorCode.RED
与1是相等的,
但真实的结果却是 False
,RED是一项枚举,枚举有 name
和 value
两个属性,
必须通过 value
才能获得真实的枚举值。
print(ColorCode.RED.value == 1) # True
True
或者换一个思路,将枚举值转成枚举类型。
print(ColorCode.RED == ColorCode(1)) # True
True
ColorCode(1))
的结果正是 ColorCode.RED
。