别再说Python没有枚举类型了,好好看看

枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表示某些特定的有限集合,例如星期、月份、状态等。
Python 的原生类型(Built-in types)里并没有专门的枚举类型,但是我们可以通过很多方法来实现它,例如字典、类等:
MiracleLove = {'MON': '林志玲', 'TUS': '陈意涵', 'WEN': '张柏芝', 'THU': '辛芷蕾', 'FRI': '周冬雨'}
class MiracleLove:
MON = '林志玲'
TUS = '陈意涵'
WEN = '张柏芝'
THU = '辛芷蕾'
FRI = '周冬雨'
上面两种方法可以看做是简单的枚举类型的实现。
如果只在局部范围内用到了这样的枚举变量是没有问题的。
但问题在于它们都是可变的(mutable),也就是说可以在其它地方被修改从而影响其正常使用:
MiracleLove['MON'] = MiracleLove['FRI']
print(MiracleLove)
通过类定义的枚举甚至可以实例化,变得不伦不类:
ml = MiracleLove()
print(ml.MON)
MiracleLove.MON = 2
print(ml.MON)
当然也可以使用不可变类型(immutable),例如元组,但是这样就失去了枚举类型的本意,将标签退化为无意义的变量:
MiracleLove = ('R', 'G', 'B')
print(MiracleLove[0], MiracleLove[1], MiracleLove[2])
为了提供更好的解决方案,Python 通过 PEP 435 在 3.4 版本中添加了 enum 标准库,3.4 之前的版本也可以通过 pip install enum 下载兼容支持的库。
enum 提供了 Enum/IntEnum/unique 三个工具,用法也非常简单,可以通过继承 Enum/IntEnum 定义枚举类型,其中 IntEnum 限定枚举成员必须为(或可以转化为)整数类型,而 unique 方法可以作为修饰器限定枚举成员的值不可重复:
from enum import Enum, IntEnum, unique
try:
@unique
class MiracleLove(Enum):
MON = '林志玲'
TUS = '陈意涵'
WEN = '张柏芝'
THU = '辛芷蕾'
FRI = '周冬雨'
except ValueError as e:
print(e)
# duplicate values found in <enum 'MiracleLove'>: FRI -> MON
try:
class MiracleLove(IntEnum):
MON = 1
TUS = 2
WEN = 3
THU = 4
FRI = '周冬雨'
except ValueError as e:
print(e)
# invalid literal for int() with base 10: '周冬雨'
更有趣的是 Enum 的成员均为单例(Singleton),并且不可实例化,不可更改:
class MiracleLove(Enum):
MON = '林志玲'
TUS = '陈意涵'
WEN = '张柏芝'
THU = '辛芷蕾'
FRI = '周冬雨'
try:
MiracleLove.MON = 2
except AttributeError as e:
print(e)
# Cannot reassign members.
虽然不可实例化,但可以将枚举成员赋值给变量:
mon = MiracleLove(0)
tus = MiracleLove(1)
wen = MiracleLove(2)
print(mon, tus, wen)
# MiracleLove.MON
# MiracleLove.TUS
# MiracleLove.WEN
也可以进行比较判断:
print(mon is MiracleLove.MON)
print(mon == MiracleLove.MON)
print(mon is tus)
print(wen != MiracleLove.TUS)
print(mon == 0) # 不等于任何非本枚举类的值
# True
# True
# False
# True
# False
最后一点,由于枚举成员本身也是枚举类型,因此也可以通过枚举成员找到其它成员:
print(mon.TUS)
print(mon.TUS.WEN.MON)
# MiracleLove.TUS
# MiracleLove.MON
但是要谨慎使用这一特性,因为可能与成员原有的命名空间中的名称相冲突:
print(mon.name, ':', mon.value)
class Attr(Enum):
name = 'NAME'
value = 'VALUE'
print(Attr.name.value, Attr.value.name)
# R : 0
# NAME value
总结:
enum 模块的用法很简单,功能也很明确,但是其实现方式却非常值得学习。如果你想更深入了解更多 Python 中关于 Class 和 Metaclass 的黑魔法,又不知道如何入手,那么不妨阅读一下 enum 的源码。
关注公众号「Python专栏」,后台回复「腾讯架构资源1」,获取由腾讯架构师整理的大数据学习全套资源包!

别再说Python没有枚举类型了,好好看看的更多相关文章
- Python 的枚举类型
起步 Python 中的枚举类型 Python 的原生类型中并不包含枚举类型.为了提供更好的解决方案,Python 通过 PEP 435 在 3.4 版本中添加了 enum 标准库. 枚举类型可以看作 ...
- Python面向对象-枚举类型enum
枚举类型:在实际问题中,有些变量的值被限定在一个有限的范围内.例如:一个星期有且只有7天,一年有且只有十二个月,一个班每周有6门课程等等.如果把这些量说明为整型.字符串或者其他类型显然是不合适.编程界 ...
- python:枚举类型
1.什么是枚举类型? 枚举类型可以看做是一系列常量的集合,通常用于表示某些有限且固定的集合,例如月份(一年有12个月).星期(一星期有七天).季节(一年四个季节)等. 2.枚举的定义 定义枚举首先要导 ...
- Python的枚举类型
Python的 Python的没有我们有两种用法: 创建Enum的实例 创建Enum的subclass 创建Enum的实例 from enum import Enum, unique Month = ...
- Python 中的枚举类型~转
Python 中的枚举类型 摘要: 枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表示某些特定的有限集合,例如星期.月份.状态等. 枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表 ...
- Python中模拟enum枚举类型的5种方法分享
这篇文章主要介绍了Python中模拟enum枚举类型的5种方法分享,本文直接给出实现代码,需要的朋友可以参考下 以下几种方法来模拟enum:(感觉方法一简单实用) 复制代码代码如下: # way1 ...
- 人生苦短之Python枚举类型enum
枚举类型enum是比较重要的一个数据类型,它是一种数据类型而不是数据结构,我们通常将一组常用的常数声明成枚举类型方便后续的使用.当一个变量有几种可能的取值的时候,我们将它定义为枚举类型.在Python ...
- python 枚举类型
在python中枚举是一种类(Enum,IntEnum),存放在enum模块中.枚举类型可以给一组标签赋予一组特定的值. 枚举的特点: 枚举类中不能存在相同的标签名 枚举是可迭代的 不同的枚举标签可以 ...
- PyQt(Python+Qt)学习随笔:Model中项的标记flags取值及枚举类型Qt.ItemFlag
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在Model中的项可以通过flags()方法查询对应项是否能被选择.拖拽或其他操作,对应的返回值类型 ...
随机推荐
- Netty5服务端源码解析
Netty5源码解析 今天让我来总结下netty5的服务端代码. 服务端(ServerBootstrap) 示例代码如下: import io.netty.bootstrap.ServerBootst ...
- supermap中预览osgb格式的倾斜摄影文件
参考: https://zhidao.baidu.com/question/136723493545478005.html 使用的是SuperMap IDesktop 9D,操作方法如下: 打开超图, ...
- MyBatis sqlsession 简化 使用工具类创建
2019-04-09 @Test public void Test() throws Exception { // 1.读取配置文件 String resource = "mybatis-c ...
- mysql 8.0 密码加密方式的坑
问题:新安装好MySQL 8.0和Navicat之后,连接时总是报: 1251 Client does not support authentication protocol requested by ...
- 深入理解CPP与C中bsearch函数的用法
·使用besearch函数的前提(一些废话) 首先让我们先亮出二分法的定义: https://baike.baidu.com/item/二分法/1364267 以及二分法实现的方法: https:// ...
- 2019年3月2日-小雨.md
2019年3月2日, 星期六 开学已经一周了,时间好像限制了自己进步的脚步,一个人的精力有限,想做好方方面面实在是太难了,有很多事儿最后都没做的完美.相反,自己应该放下繁琐的包袱,简简单单的干一件事儿 ...
- HTML 5将给开发者带来什么?
在新的时代里,相信网页技术会伴随HTML 5的来临进入大洗牌的局面,HTML 5旨在解决Web中的交互,媒体,本地操作等问题,一些浏览器已经尝试支持HTML 5的一些功能,而开发者们有望最终从那些We ...
- 同步计数器 CountDownLatch
CountDownLatch 是一个同步工具类,它允许一个或多个线程一直等待,直到其他线程的操作执行完后再执行. CountDownLatch 是通过一个计数器来实现的,计数器的初始值为线程的数量.每 ...
- docker pull 镜像报错
[root@localhost ~]# docker pull ningx Using default tag: latest Trying to pull repository docker.io/ ...
- 使用Jacksum对文件夹和文件生成checksum
Jacksum 是一个java开源工具, 用来 给单个文件生成checksum, 也可以给整个文件中所有文件生成checksum,生产的checksum 可以是MD系列,也可sha. 你可以参考 官 ...