Python 枚举数据类型(Enum)

什么是enum,为什么需要它?

枚举类型,也称为enum,是一种数据类型,由一组命名值组成。这些可枚举的命名值充当计算机语言中的常量。例如,COLOR枚举可以包括诸如RED, GREEN, BLUE等命名值。这些命名值都是大写,以区别于变量。

为什么要使用枚举呢?

可以想像这样一种情景:需要在网站中将用户的性别限制为MALE, FEMALE和N/A。当然,字符串列表也可以胜任,如user.gender='MALE',user.gender='FEMALE'。但使用字符串作为性别属性值显得不够强壮,程序员在使用过程中容易出错或者受到恶意攻击。程序员很容易将'MALE'误拼写为'ALE',或者将'FEMALE'误拼写为'EMAIL',代码虽然仍可以运行,但会产生严重结果。攻击者可能会仔细构建垃圾字符串值,导致系统崩溃或获取根访问权限。如果使用枚举,则可将user.gender属性的值限制在有限的值列表中,这样前面提到的问题就不会出现了。

Python中使用枚举的技巧与建议

enum有助于为属性限制可选的值,这在实际编程中非常有用。在处理数据库时,enum在Python和数据库管理系统中应用是等同的,这样就可以避免很多难以发现的bug。

使用enum可以有效地保护系统,使其杜绝恶意输入。在系统接受用户输入前,一定要检查输入的值。

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为字符串的数字,也不会报错。

  • 11
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值