枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表示某些特定的有限集合,例如星期、月份、状态等。

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专栏」,后台回复「腾讯架构资源1」,获取由腾讯架构师整理的大数据学习全套资源包!

别再说Python没有枚举类型了,好好看看的更多相关文章

  1. Python 的枚举类型

    起步 Python 中的枚举类型 Python 的原生类型中并不包含枚举类型.为了提供更好的解决方案,Python 通过 PEP 435 在 3.4 版本中添加了 enum 标准库. 枚举类型可以看作 ...

  2. Python面向对象-枚举类型enum

    枚举类型:在实际问题中,有些变量的值被限定在一个有限的范围内.例如:一个星期有且只有7天,一年有且只有十二个月,一个班每周有6门课程等等.如果把这些量说明为整型.字符串或者其他类型显然是不合适.编程界 ...

  3. python:枚举类型

    1.什么是枚举类型? 枚举类型可以看做是一系列常量的集合,通常用于表示某些有限且固定的集合,例如月份(一年有12个月).星期(一星期有七天).季节(一年四个季节)等. 2.枚举的定义 定义枚举首先要导 ...

  4. Python的枚举类型

    Python的 Python的没有我们有两种用法: 创建Enum的实例 创建Enum的subclass 创建Enum的实例 from enum import Enum, unique Month = ...

  5. Python 中的枚举类型~转

    Python 中的枚举类型 摘要: 枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表示某些特定的有限集合,例如星期.月份.状态等. 枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表 ...

  6. Python中模拟enum枚举类型的5种方法分享

    这篇文章主要介绍了Python中模拟enum枚举类型的5种方法分享,本文直接给出实现代码,需要的朋友可以参考下   以下几种方法来模拟enum:(感觉方法一简单实用) 复制代码代码如下: # way1 ...

  7. 人生苦短之Python枚举类型enum

    枚举类型enum是比较重要的一个数据类型,它是一种数据类型而不是数据结构,我们通常将一组常用的常数声明成枚举类型方便后续的使用.当一个变量有几种可能的取值的时候,我们将它定义为枚举类型.在Python ...

  8. python 枚举类型

    在python中枚举是一种类(Enum,IntEnum),存放在enum模块中.枚举类型可以给一组标签赋予一组特定的值. 枚举的特点: 枚举类中不能存在相同的标签名 枚举是可迭代的 不同的枚举标签可以 ...

  9. PyQt(Python+Qt)学习随笔:Model中项的标记flags取值及枚举类型Qt.ItemFlag

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 在Model中的项可以通过flags()方法查询对应项是否能被选择.拖拽或其他操作,对应的返回值类型 ...

随机推荐

  1. apache poi 读取xlsx并导出为json(没考虑xls)

    1.用到的jar包:fastjson-1.2.9.poi(poi-3.15.poi-ooxml-3.15.poi-ooxml-schemas-3.15.xmlbeans-2.6.0.commons-c ...

  2. MBR分区操作-增加、扩展、删除

    MBR分区操作-增加.扩展.删除 GPT分区参考 http://www.blogjava.net/haha1903/archive/2011/12/21/366942.html l  fdisk 显示 ...

  3. SQLSERVER的递归

    实际项目如遇到按照如地区这样树状结构的条件递归查询数据的场景中,可以使用. CREATE FUNCTION [dbo].[GetAllChildrenTypeById] ( ) ) RETURNS T ...

  4. qt之数据库对照片的存取

    需要确保数据库连接上 QOCI为驱动 //oracle 数据库连接 //需要在执行文件目录添加 oci.dll oraociei11.dll QSqlDatabase db = QSqlDatabas ...

  5. javascript 数据类型 -- 检测

    一.前言 在上一篇博文中 Javascript 数据类型 -- 分类 中,我们梳理了 javascript 的基本类型和引用类型,并提到了一些冷知识.大概的知识框架如下: 这篇博文就讲一下在写代码的过 ...

  6. Egret的容器--删除对象,遮罩

    class P91F extends egret.Sprite { public constructor() { super(); this.addEventListener(egret.Event. ...

  7. socketserver模块TCP和UDP协议形式

    # >>>>>>>>>>>>>>>>>>>>服务端socketserver模块通 ...

  8. ionic-基于angularjs实现的多级城市选择组件

    大家都知道在移动端的选择地区组件,大部分都是模拟IOS选择器做的城市三级联动,但是在IOS上比较好,在Android上因为有的不支持ion-scroll.所以就会出现滚动不会自动回滚到某一个的正中间. ...

  9. cadence钻孔文件及光绘文件的生成

    完成PCB布线之后,需要生成钻孔文件和光绘文件交给PCB厂家制作PCB板,下面总结详细方法!

  10. 在IIS上新发布的网站,样式与js资源文件加载不到(资源文件和网页同一个域名下)

    在IIS上新发布的网站,网站能打开,但样式与js资源文件加载不到(资源文件和网页是同一个域名下,例如:网页www.xxx.com/index.aspx,图片www.xxx.com/pic.png). ...