深入了解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中的控制流语句的知识点
Apr 14 Python
Python变量赋值的秘密分享
Apr 03 Python
Python人脸识别第三方库face_recognition接口说明文档
May 03 Python
python 实现让字典的value 成为列表
Dec 16 Python
django处理select下拉表单实例(从model到前端到post到form)
Mar 13 Python
Python如何避免文件同名产生覆盖
Jun 09 Python
tensorflow 2.0模式下训练的模型转成 tf1.x 版本的pb模型实例
Jun 22 Python
如何基于Python Matplotlib实现网格动画
Jul 20 Python
python生成xml时规定dtd实例方法
Sep 21 Python
详解Python遍历列表时删除元素的正确做法
Jan 07 Python
Python词云的正确实现方法实例
May 08 Python
Python Django模型详解
Oct 05 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
php strtotime 函数UNIX时间戳
2009/01/14 PHP
PHP生成自适应大小的缩略图类及使用方法分享
2014/05/06 PHP
php使用Session和文件统计在线人数
2015/07/04 PHP
注意!PHP 7中不要做的10件事
2016/09/18 PHP
jquery 1.3.2 IE8中的一点点的小问题解决方法
2009/07/10 Javascript
解决遍历时Array.indexOf产生的性能问题
2012/07/03 Javascript
在jQuery ajax中按钮button和submit的区别分析
2012/10/07 Javascript
js 三级关联菜单效果实例
2013/08/13 Javascript
使用jQuery避免鼠标双击的解决方案
2013/08/21 Javascript
JS实现下拉菜单赋值到文本框的方法
2015/08/18 Javascript
分享两段简单的JS代码防止SQL注入
2016/04/12 Javascript
js实现精确到秒的日期选择器完整实例
2016/04/30 Javascript
浅谈JavaScript 标准对象
2016/06/02 Javascript
全面了解函数声明与函数表达式、变量提升
2016/08/09 Javascript
一篇文章搞定JavaScript类型转换(面试常见)
2017/01/21 Javascript
nodejs个人博客开发第六步 数据分页
2017/04/12 NodeJs
vue中各选项及钩子函数执行顺序详解
2018/08/25 Javascript
JavaScript惰性载入函数实例分析
2019/03/27 Javascript
[01:18:36]LGD vs VP Supermajor 败者组决赛 BO3 第一场 6.10
2018/07/04 DOTA
python赋值操作方法分享
2013/03/23 Python
python中 ? : 三元表达式的使用介绍
2013/10/09 Python
python3编写C/S网络程序实例教程
2014/08/25 Python
Python 基于Twisted框架的文件夹网络传输源码
2016/08/28 Python
使用python存储网页上的图片实例
2018/05/22 Python
Python实现将通信达.day文件读取为DataFrame
2018/12/22 Python
python 通过类中一个方法获取另一个方法变量的实例
2019/01/22 Python
python浪漫表白源码
2019/04/05 Python
Python实现将HTML转成PDF的方法分析
2019/05/04 Python
Python3.5 + sklearn利用SVM自动识别字母验证码方法示例
2019/05/10 Python
python中时间转换datetime和pd.to_datetime详析
2019/08/11 Python
CSS3教程(1):什么是CSS3
2009/04/02 HTML / CSS
综合测评自我鉴定
2013/10/08 职场文书
实习鉴定范文
2013/12/19 职场文书
国际会议邀请函范文
2014/01/16 职场文书
2014党员学习兰辉先进事迹思想汇报
2014/09/17 职场文书
Python基础之常用库常用方法整理
2021/04/30 Python