深入了解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实现域名系统(DNS)正向查询的方法
Apr 19 Python
python实现聚类算法原理
Feb 12 Python
利用scrapy将爬到的数据保存到mysql(防止重复)
Mar 31 Python
django反向解析URL和URL命名空间的方法
Jun 05 Python
Python图像滤波处理操作示例【基于ImageFilter类】
Jan 03 Python
详解python 3.6 安装json 模块(simplejson)
Apr 02 Python
python 判断linux进程,并杀死进程的实现方法
Jul 01 Python
Python SQLAlchemy入门教程(基本用法)
Nov 11 Python
Python 整行读取文本方法并去掉readlines换行\n操作
Sep 03 Python
Python实现淘宝秒杀功能的示例代码
Jan 19 Python
Python 文本滚动播放器的实现代码
Apr 25 Python
python单元测试之pytest的使用
Jun 07 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
咖啡豆的最常见发酵处理方法,详细了解一下
2021/03/03 冲泡冲煮
浅析Yii2 GridView 日期格式化并实现日期可搜索教程
2016/04/22 PHP
PHP延迟静态绑定的深入讲解
2018/04/02 PHP
Javascript 颜色渐变效果的实现代码
2013/10/01 Javascript
javascript获取select的当前值示例代码(兼容IE/Firefox/Opera/Chrome)
2013/12/17 Javascript
jquery操作下拉列表、文本框、复选框、单选框集合(收藏)
2014/01/08 Javascript
jquery对单选框,多选框,文本框等常见操作小结
2014/01/08 Javascript
jQuery中;function($,undefined) 前面的分号的用处
2014/12/17 Javascript
jQuery实现类似淘宝网图片放大效果的方法
2015/07/08 Javascript
jquery实现红色竖向多级向右展开的导航菜单效果
2015/08/31 Javascript
JavaScript模拟push
2016/03/06 Javascript
jQuery实现调整表格单列顺序完整实例
2016/06/20 Javascript
JS解决position:sticky的兼容性问题的方法
2017/10/17 Javascript
使用JS获取SessionStorage的值
2018/01/12 Javascript
js遍历添加栏目类添加css 再点击其它删除css【推荐】
2018/06/12 Javascript
vue使用Font Awesome的方法步骤
2019/02/26 Javascript
vue登录页面cookie的使用及页面跳转代码
2019/07/10 Javascript
vue.config.js常用配置详解
2019/11/14 Javascript
解决vant框架做H5时踩过的坑(下拉刷新、上拉加载等)
2020/11/11 Javascript
js canvas实现五子棋小游戏
2021/01/22 Javascript
推荐11个实用Python库
2015/01/23 Python
python有几个版本
2020/06/17 Python
详解python os.path.exists判断文件或文件夹是否存在
2020/11/16 Python
python 实现数据库中数据添加、查询与更新的示例代码
2020/12/07 Python
HTML5 拖放功能实现代码
2016/07/14 HTML / CSS
我看到了用指针调用函数的不同语法形式
2014/07/16 面试题
公司财务总监岗位职责
2013/12/14 职场文书
庆祝教师节活动方案
2014/01/31 职场文书
学习礼仪心得体会
2014/09/01 职场文书
2015年小学财务工作总结
2015/07/20 职场文书
女性励志书籍推荐
2019/08/19 职场文书
golang 如何用反射reflect操作结构体
2021/04/28 Golang
Windows Server 2012配置DNS服务器的方法
2022/04/29 Servers
解决vue自定义组件@click点击失效问题
2022/04/30 Vue.js
oracle数据库去除重复数据
2022/05/20 Oracle
NoSQL优缺点与MongoDB数据库简介
2022/06/05 MongoDB