深入了解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比较文件夹比另一同名文件夹多出的文件并复制出来的方法
Mar 05 Python
浅析Python中signal包的使用
Nov 13 Python
用python写个自动SSH登录远程服务器的小工具(实例)
Jun 17 Python
Python随机生成均匀分布在三角形内或者任意多边形内的点
Dec 14 Python
用python处理MS Word的实例讲解
May 08 Python
对Tensorflow中的变量初始化函数详解
Jul 27 Python
selenium3+python3环境搭建教程图解
Dec 07 Python
Python3.4学习笔记之常用操作符,条件分支和循环用法示例
Mar 01 Python
Python 解码Base64 得到码流格式文本实例
Jan 09 Python
pytorch torchvision.ImageFolder的用法介绍
Feb 20 Python
用Python selenium实现淘宝抢单机器人
Jun 18 Python
Python学习之包与模块详解
Mar 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
第1次亲密接触PHP5(1)
2006/10/09 PHP
PHP新手上路(十三)
2006/10/09 PHP
PHP初学者常见问题集合 修正版(21问答)
2010/03/23 PHP
php制作中间带自己定义图片二维码的方法
2014/01/27 PHP
推荐一本PHP程序猿都应该拜读的书
2014/12/31 PHP
PHP常量define和const的区别详解
2019/05/18 PHP
js模拟点击事件实现代码
2012/11/06 Javascript
jquery ajax修改全局变量示例代码
2013/11/08 Javascript
js+html5实现canvas绘制简单矩形的方法
2015/06/05 Javascript
解决webpack -p压缩打包react报语法错误的方法
2017/07/03 Javascript
原生JS获取元素的位置与尺寸实现方法
2017/10/18 Javascript
Vue.JS项目中5个经典Vuex插件
2017/11/28 Javascript
详解Puppeteer 入门教程
2018/05/09 Javascript
vue生命周期的探索
2019/04/03 Javascript
解决Idea、WebStorm下使用Vue cli脚手架项目无法使用Webpack别名的问题
2019/10/11 Javascript
微信小程序实现侧边栏分类
2019/10/21 Javascript
详解Vue的ref特性的使用
2020/01/24 Javascript
jQuery事件模型默认行为执行顺序及trigger()与 triggerHandler()比较实例分析
2020/04/30 jQuery
python中将字典转换成其json字符串
2014/07/16 Python
零基础学Python(一)Python环境安装
2014/08/20 Python
Flask框架中request、请求钩子、上下文用法分析
2019/07/23 Python
Python实现在Windows平台修改文件属性
2020/03/05 Python
Jupyter Notebook远程登录及密码设置操作
2020/04/10 Python
完美解决pycharm 不显示代码提示问题
2020/06/02 Python
CSS3 Calc实现滚动条出现页面不跳动问题
2017/09/14 HTML / CSS
美国时尚配饰品牌:Dooney & Bourke
2017/11/14 全球购物
中间件的定义
2016/08/09 面试题
旅游管理本科生求职信
2013/10/14 职场文书
大学生怎样进行自我评价
2013/12/07 职场文书
测控技术与仪器个人求职信范文
2013/12/30 职场文书
请假条范文大全
2014/04/10 职场文书
消防安全责任书
2014/04/14 职场文书
《社戏》教学反思
2014/04/15 职场文书
社团活动总结怎么写
2014/06/30 职场文书
学校政风行风评议心得体会
2014/10/21 职场文书
三好学生评选事迹材料(2016精选版)
2016/02/25 职场文书