深入了解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中实现php的var_dump函数功能
Jan 21 Python
python中django框架通过正则搜索页面上email地址的方法
Mar 21 Python
Python线程的两种编程方式
Apr 14 Python
在arcgis使用python脚本进行字段计算时是如何解决中文问题的
Oct 18 Python
python实现搜索本地文件信息写入文件的方法
Feb 22 Python
Python文本特征抽取与向量化算法学习
Dec 22 Python
pandas DataFrame数据转为list的方法
Apr 11 Python
Django框架模板注入操作示例【变量传递到模板】
Dec 19 Python
python and or用法详解
Jun 26 Python
Python学习笔记之While循环用法分析
Aug 14 Python
Mac中PyCharm配置Anaconda环境的方法
Mar 04 Python
python中round函数如何使用
Jun 19 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
删除无限分类并同时删除它下面的所有子分类的方法
2010/08/08 PHP
php中过滤非法字符的具体实现
2013/10/29 PHP
php ZipArchive压缩函数详解实例
2013/11/06 PHP
PHP实现更改hosts文件的方法示例
2017/08/08 PHP
php统计数组不同元素的个数的实例方法
2019/09/26 PHP
优秀js开源框架-jQuery使用手册(1)
2007/03/10 Javascript
JavaScript学习历程和心得小结
2010/08/16 Javascript
学习JavaScript的最佳方法分享
2011/10/21 Javascript
js事件监听机制(事件捕获)总结
2014/08/08 Javascript
Javascript基础知识(二)事件
2014/09/29 Javascript
jQuery使用$.ajax提交表单完整实例
2015/12/11 Javascript
javascript图片切换综合实例(循环切换、顺序切换)
2016/01/13 Javascript
下一代Bootstrap的5个特点 超酷炫!
2016/06/17 Javascript
JS实现兼容各种浏览器的获取选择文本的方法【测试可用】
2016/06/21 Javascript
使用开源工具制作网页验证码的方法
2016/10/17 Javascript
vuejs指令详解
2017/02/07 Javascript
关于Sequelize连接查询时inlude中model和association的区别详解
2017/02/27 Javascript
jQuery使用ajax_动力节点Java学院整理
2017/07/05 jQuery
react-native fetch的具体使用方法
2017/11/01 Javascript
Python的类实例属性访问规则探讨
2015/01/30 Python
浅谈tensorflow1.0 池化层(pooling)和全连接层(dense)
2018/04/27 Python
Flask web开发处理POST请求实现(登录案例)
2018/07/26 Python
Python 类方法和实例方法(@classmethod),静态方法(@staticmethod)原理与用法分析
2019/09/20 Python
浅谈Django QuerySet对象(模型.objects)的常用方法
2020/03/28 Python
用python按照图像灰度值统计并筛选图片的操作(PIL,shutil,os)
2020/06/04 Python
python算的上脚本语言吗
2020/06/22 Python
Django rest framework分页接口实现原理解析
2020/08/21 Python
Eyeko美国:屡获殊荣的睫毛膏、眼线笔和眉妆
2018/07/05 全球购物
介绍一下如何利用路径遍历进行攻击及如何防范
2014/01/19 面试题
Linux管理员面试题 Linux admin interview questions
2014/11/01 面试题
物业管理应届生求职信
2013/10/28 职场文书
事业单位请假制度
2014/01/13 职场文书
家长会欢迎标语
2014/06/24 职场文书
人事专员岗位说明书
2014/07/29 职场文书
上课随便讲话检讨书
2014/09/12 职场文书
2016年“5.12”护士节慰问信
2015/11/30 职场文书