文档章节

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

o
 osc_a22drz29
发布于 2019/03/27 20:59
字数 893
阅读 8
收藏 0

精选30+云产品,助力企业轻松上云!>>>

枚举

枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表示某些特定的有限集合,例如星期、月份、状态等。

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」,获取由腾讯架构师整理的大数据学习全套资源包!

<img src="https://img2018.cnblogs.com/blog/649191/201902/649191-20190228222044609-1976101388.jpg" width="300" height="300" alt="Python专栏二维码" style="display:block; margin: 0 auto;" />

o
粉丝 0
博文 500
码字总数 0
作品 0
私信 提问
加载中
请先登录后再评论。
别再说Python没有枚举类型了,好好看看

枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表示某些特定的有限集合,例如星期、月份、状态等。 Python 的原生类型(Built-in types)里并没有专门的枚举类型,但是我们可以通...

上海小胖
2019/03/27
40
0
求你了,别再使用 pprint 打印字典了

首发于微信公众号:Python编程时光 在线博客地址:http://python.iswbm.com/en/latest/c02/c0214.html 1. 吐槽问题 Python 里的 pprint 你应该很熟悉了吧? 随便在搜索引擎上搜索如何打印漂亮...

王一白
05/09
0
0
pymssql中文乱码终极解决之道~逃

#pymssql中文乱码#最近用Python写的一些小脚本,使用pymssql连接数据库。 在我自个的笔记本上是好好的,在Debian服务器上是好的,只要放到公司电脑上就乱码,必须用这个进行转码。 我对比了电...

小生纳兰
03/11
82
0
Python2寿命只剩一个月啦!还不快赶紧学起Python3酷炫到爆的新特性!

本文分享自微信公众号 - 云爬虫技术研究笔记(cloudcrawler)。 如有侵权,请联系 support@oschina.cn 删除。 本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。...

玛丽奥应该会手撕鸡
2019/11/12
0
0
Python3 与 C# 扩展之~基础衍生

本文适应人群: or 基础巩固 代码裤子: https://github.com/lotapp/BaseCode 在线编程: https://mybinder.org/v2/gh/lotapp/BaseCode/master 在线预览:http://github.lesschina.com/pytho......

osc_7831jj0v
2018/07/07
2
0

没有更多内容

加载失败,请刷新页面

加载更多

敖丙20 张图揭开内存管理的迷雾

前言 之前有不少读者跟我反馈,能不能写图解操作系统? 既然那么多读者想看,我最近就在疯狂的复习操作系统的知识。 操作系统确实是比较难啃的一门课,至少我认为比计算机网络难太多了,但它...

敖丙
07/02
15
0
拉勾网拉你上勾

预览 需求简介 拉勾网是一个互联网行业的一个招聘网站,上面有许多职位,于是乎,小编想提取指定职位的基本信息(职位名,薪水,工作经验,工作地点,教育背景),然后插入 MongoDB 数据库,...

木下瞳
2019/04/17
20
0
我是一个线程(第一人称)

来源 | 转自 码农翻身 作者 | 刘欣 全文总共 | 4600 字 预计阅读时间 | 12 分钟 第一回 初生牛犊 我是一个线程,我一出生就被编了个号:0x3704,然后被领到一个昏暗的屋子里,在这里我发现了...

geniusian
2019/11/04
18
0
SkyWalking 权限认证

版本:7.0.0 描述 为了数据传输安全,确保网络连接是安全的。采用 Token 认证确保采集的应用数据是被信任的。 当前版本,仅支持简单的字符串 Token 配置 代理端配置文件agent.config设置 # ...

zm123321
50分钟前
17
0
是否允许实体正文进行HTTP DELETE请求? - Is an entity body allowed for an HTTP DELETE request?

问题: When issuing an HTTP DELETE request, the request URI should completely identify the resource to delete. 发出HTTP DELETE请求时,请求URI应该完全标识要删除的资源。 However,......

javail
昨天
27
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部