深入了解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随机生成手机号、数字的方法详解
Jul 21 Python
python 中的divmod数字处理函数浅析
Oct 17 Python
python实时监控cpu小工具
Jun 21 Python
根据DataFrame某一列的值来选择具体的某一行方法
Jul 03 Python
python安装numpy和pandas的方法步骤
May 27 Python
详解Django将秒转换为xx天xx时xx分
Sep 27 Python
Python 如何操作 SQLite 数据库
Aug 17 Python
python3让print输出不换行的方法
Aug 24 Python
Python爬虫制作翻译程序的示例代码
Feb 22 Python
浅析Python实现DFA算法
Jun 26 Python
python 中的jieba分词库
Nov 23 Python
Python自动化工具之实现Excel转Markdown表格
Apr 08 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
PHP5.3.1 不再支持ISAPI
2010/01/08 PHP
php 魔术函数使用说明
2010/02/21 PHP
php判断用户是否关注微信公众号
2016/07/22 PHP
总结对比php中的多种序列化
2016/08/28 PHP
php 猴子摘桃的算法
2017/06/20 PHP
php中文语义分析实现方法示例
2019/09/28 PHP
基于jQuery的日期选择控件
2009/10/27 Javascript
JS 对象介绍
2010/01/20 Javascript
ExtJs grid行 右键菜单的两种方法
2010/06/19 Javascript
实现web打印的各种方法介绍及实现代码
2013/01/09 Javascript
js中通过父级进行查找定位元素
2014/06/15 Javascript
SWFObject基本用法实例分析
2015/07/20 Javascript
jQuery添加和删除指定标签的方法
2015/12/16 Javascript
js表单元素checked、radio被选中的几种方法(详解)
2016/08/22 Javascript
使用JS正则表达式 替换括号,尖括号等
2016/11/29 Javascript
前端框架学习总结之Angular、React与Vue的比较详解
2017/03/14 Javascript
JavaScript中利用Array filter() 方法压缩稀疏数组
2018/02/24 Javascript
vue服务端渲染添加缓存的方法
2018/09/18 Javascript
微信小程序实现的日期午别医生排班表功能示例
2019/01/09 Javascript
JS实现从对象获取对象中单个键值的方法示例
2019/06/05 Javascript
jQuery实现评论模块
2020/08/19 jQuery
python使用装饰器和线程限制函数执行时间的方法
2015/04/18 Python
使用PyInstaller将Python程序文件转换为可执行程序文件
2016/07/08 Python
非递归的输出1-N的全排列实例(推荐)
2017/04/11 Python
Python 编码规范(Google Python Style Guide)
2018/05/05 Python
Python字符串对齐、删除字符串不需要的内容以及格式化打印字符
2021/01/23 Python
Pamela Love官网:纽约设计师Pamela Love的精美、时尚和穿孔珠宝
2020/10/19 全球购物
介绍一些UNIX常用简单命令
2014/11/11 面试题
超越自我演讲稿
2014/05/21 职场文书
教育系统干部作风整顿心得体会
2014/09/09 职场文书
2015年校长新年寄语
2014/12/08 职场文书
维稳承诺书
2015/01/20 职场文书
企业计划生育责任书
2015/05/09 职场文书
2015年小学语文教学工作总结
2015/05/25 职场文书
Python趣味挑战之用pygame实现简单的金币旋转效果
2021/05/31 Python
动漫APP软件排行榜前十名,半次元上榜,第一款由腾讯公司推出
2022/03/18 杂记