Python中的枚举数据类型
枚举的字面含义是指列出有穷集合中的所有元素,即一一列举的意思。在Python中,枚举可以视为是一种数据类型,当一个变量的取值只有几种有限的情况时,我们可以将其声明为枚举类型。例如表示周几的这一变量weekday,只有七种可能的取值,我们就可以将其声明为枚举类型。
那么枚举的类型该如何实现呢? 我们一个很直观的想法是:可以通过类的方式来实现,变量就是类,变量所有可能的取值作为类的变量。之后访问的时候,通过类名+变量名的方式就可以进行访问:
class Weekday():
monday = 1
tuesday = 2
wednesday = 3
thirsday = 4
friday = 5
saturday = 6
sunday = 7
print(Weekday.wednesday) # 3
但是这样实现枚举类型的方式存在一定的问题:
1、枚举的枚举项不能出现重复,即key不应该相同(以上例来讲,不能出现两个wednesday)
2、枚举项的值不应该允许在外部进行修改(枚举类型一般是固定下来的常量,声明好之后不能在外部随意更改)
如下所示:
class Weekday():
monday = 1
tuesday = 2
wednesday = 3
thirsday = 4
friday = 5
saturday = 6
sunday = 7
wednesday = 333
print(Weekday.wednesday) # 333
Weekday.wednesday = "星期三"
print(Weekday.wednesday) # 星期三
为了解决上述两个问题,我们可以使用Python中提供的enum模块。
enum的使用
enum模块是系统内置模块,可以直接使用import导入,但是在导入的时候,不建议使用import enum将enum模块中的所有数据都导入,一般使用的最多的就是enum模块中的Enum、IntEnum、unique这几项。
借助enum模块,我们在实现上述需求的时候,就可以这样来做:
from enum import Enum
class Weekday(Enum):
monday = 1
tuesday = 2
wednesday = 3
thirsday = 4
friday = 5
saturday = 6
sunday = 7
print(Weekday.wednesday) # Weekday.wednesday
print(type(Weekday.wednesday)) # <enum 'Weekday'>
print(Weekday.wednesday.name) # wednesday
print(Weekday.wednesday.value) # 3
我们自定义的枚举类型继承Enum基类,之后还是通过Weekday.wednesday获取得到的是枚举成员,通过.name和.value可以获得枚举成员对应的属性。
这时,如果我们在Weekday类中,声明重复的枚举成员,会产生错误:
TypeError: Attempted to reuse key: 'wednesday'
如果在外部进行枚举成员属性值的修改,也会产生错误:
AttributeError: Cannot reassign members.
这样的话,就解决之前存在的两个问题。
此外,对于枚举成员,.name和.value是其内置属性,我们还可以给枚举成员增加其他属性。实现的方式如下:
from enum import Enum
class Weekday(Enum):
monday = 1
tuesday = 2
wednesday = 3
thirsday = 4
friday = 5
saturday = 6
sunday = 7
Weekday.wednesday.label = "星期三"
Weekday.wednesday.work = "完成假期作业"
Weekday.wednesday.time = 10
print(Weekday.wednesday.label) # 星期三
print(Weekday.wednesday.work) # 完成假期作业
print(Weekday.wednesday.time) # 10
在获取枚举类型的成员时,我们可以通过类名+key的方式实现,即上面的Weekday.wednesday。此外,通过key获取枚举成员的时候,还可以使用Weekday['key']这样的方式。
也可以通过value来获取枚举成员,通过value获取枚举成员是:Weekday(value)这样的方式。
如下所示:
from enum import Enum
class Weekday(Enum):
monday = 1
tuesday = 2
wednesday = 3
thirsday = 4
friday = 5
saturday = 6
sunday = 7
Weekday.wednesday.label = "星期三"
Weekday.wednesday.work = "完成假期作业"
Weekday.wednesday.time = 10
obj_1 = Weekday.wednesday
print(obj_1.label) # 星期三
obj_2 = Weekday['wednesday']
print(obj_1.label) # 星期三
obj_3 = Weekday(3)
print(obj_3.label) # 星期三
enum的总结
1、枚举类不能用来实例化对象
例如下面的用法是错误的:
from enum import Enum
class Weekday(Enum):
monday = 1
tuesday = 2
wednesday = 3
thirsday = 4
friday = 5
saturday = 6
sunday = 7
w = Weekday()
print(w.wednesday)
2、访问枚举类中的某个枚举成员,可以有三种方式,详见上面使用部分的介绍。
3、枚举类里面定义的 key = value,在类外部不能修改value值,详见上面使用部分的介绍。
4、枚举成员可以用来比较,使用==或者is。
from enum import Enum
class Weekday(Enum):
monday = 1
tuesday = 2
wednesday = 3
thirsday = 4
friday = 5
saturday = 6
sunday = 7
obj_1 = Weekday.wednesday
obj_2 = Weekday['wednesday']
obj_3 = Weekday(3)
print(obj_1==obj_2==obj_3) # True
print(obj_1 is obj_2 is obj_3) # True
5、继承Enum基类之后,一个枚举类中的key和value,key不能相同,但是value可以相同。
from enum import Enum
class Weekday(Enum):
monday = 1
tuesday = 2
wednesday = 3
thirsday = 4
friday = 5
saturday = 6
sunday = 7
test = 3
print(Weekday.test.value) # 3
如果想让value也不相同的话,可以导入unique。如下所示:
from enum import Enum, unique
@unique
class Weekday(Enum):
monday = 1
tuesday = 2
wednesday = 3
thirsday = 4
friday = 5
saturday = 6
sunday = 7
test = 3
print(Weekday.test.value) # 3
此时的代码会报如下错误:
6、如果要枚举类中的Value只能是整型数字,那么,可以导入IntEnum,然后继承IntEnum即可。注意,此时,如果value为字符串的数字,也不会报错。