深入了解Python枚举类型的相关知识


Posted in Python onJuly 09, 2019

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

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 相关文章推荐
Python解析网页源代码中的115网盘链接实例
Sep 30 Python
python实现获取客户机上指定文件并传输到服务器的方法
Mar 16 Python
解决Python 遍历字典时删除元素报异常的问题
Sep 11 Python
详解Python 2.6 升级至 Python 2.7 的实践心得
Apr 27 Python
Flask框架实现给视图函数增加装饰器操作示例
Jul 16 Python
Python中的 enum 模块源码详析
Jan 09 Python
Django框架创建mysql连接与使用示例
Jul 29 Python
基于python实现微信好友数据分析(简单)
Feb 16 Python
使用Python3 poplib模块删除服务器多天前的邮件实现代码
Apr 24 Python
利用Python实现某OA系统的自动定位功能
May 27 Python
Python中tkinter的用户登录管理的实现
Apr 22 Python
python 爬取吉首大学网站成绩单
Jun 02 Python
Python 的AES加密与解密实现
Jul 09 #Python
python+numpy按行求一个二维数组的最大值方法
Jul 09 #Python
使用Python轻松完成垃圾分类(基于图像识别)
Jul 09 #Python
Python分析彩票记录并预测中奖号码过程详解
Jul 09 #Python
python求最大值,不使用内置函数的实现方法
Jul 09 #Python
pandas的连接函数concat()函数的具体使用方法
Jul 09 #Python
python爬虫的一个常见简单js反爬详解
Jul 09 #Python
You might like
模拟OICQ的实现思路和核心程序(一)
2006/10/09 PHP
DOM XPATH获取img src值的query
2013/09/23 PHP
用php简单实现加减乘除计算器
2014/01/06 PHP
zf框架的校验器使用使用示例(自定义校验器和校验器链)
2014/03/13 PHP
jQuery+PHP发布的内容进行无刷新分页(Fckeditor)
2015/10/22 PHP
Prototype Number对象 学习
2009/07/19 Javascript
js实现Form栏显示全格式时间时钟效果代码
2015/08/19 Javascript
AngularJS 使用$sce控制代码安全检查
2016/01/05 Javascript
封装属于自己的JS组件
2016/01/27 Javascript
理解javascript中Map代替循环
2016/02/26 Javascript
VC调用javascript的几种方法(推荐)
2016/08/09 Javascript
JS调用某段SQL语句的方法
2016/10/20 Javascript
Node.js websocket使用socket.io库实现实时聊天室
2017/02/20 Javascript
JS对象创建的几种方式整理
2017/02/28 Javascript
JS兼容所有浏览器的DOMContentLoaded事件
2018/01/12 Javascript
在vue中使用css modules替代scroped的方法
2018/03/10 Javascript
[04:07]显微镜下的DOTA2第八期——英雄复活动作
2014/06/24 DOTA
python实现监控linux性能及进程消耗性能的方法
2014/07/25 Python
Python实现的异步代理爬虫及代理池
2017/03/17 Python
Python实现连接postgresql数据库的方法分析
2017/12/27 Python
python hbase读取数据发送kafka的方法
2018/12/27 Python
Python实现的爬取百度贴吧图片功能完整示例
2019/05/10 Python
微信小程序python用户认证的实现
2019/07/29 Python
浅析Python 字符编码与文件处理
2020/09/24 Python
Python eval函数介绍及用法
2020/11/09 Python
详解H5本地储存Web Storage
2017/07/03 HTML / CSS
香港艺人陈冠希创办的潮流品牌:JUICESTORE
2021/03/04 全球购物
物理系毕业生自荐书
2014/06/13 职场文书
中药学专业毕业生推荐信
2014/07/10 职场文书
党员目标管理责任书
2014/07/25 职场文书
中学生民族团结演讲稿
2014/08/27 职场文书
远程培训的心得体会
2014/09/01 职场文书
装配出错检讨书
2014/09/23 职场文书
业务员岗位职责范本
2015/04/03 职场文书
2016年学校十一国庆节活动总结
2016/04/01 职场文书
Nginx配置根据url参数重定向
2022/04/11 Servers