理解Python 枚举替代实现的缺陷,关于枚举最经典的例子大概非季节和星期莫属了,它能够以更接近自然语言的方式来表达数据,使得程序的可读性和可维护性大大提高。然而,很不幸,也许你习惯了其他语言中的枚举类型,但在Python3.4以前却并不提供。关于要不要加入枚举类型的问题就引起了不少讨论,在PEP354中曾提出增加枚举的建议,但被拒绝。于是人们充分利用Python的动态性这个特征,想出了枚举的各种替代实现方式。
1)使用类属性。
>>> class Seasons:
... Spring = 0
... Summer = 1
... Autumn = 2
... Winter = 3
...
>>> print Seasons.Spring
上面的例子可以直接简化为:
>>> class Seasons:
... Spring,Summer,Autumn,Winter=range(4)
...
2)借助函数。
>>> def enum(*posarg, **keysarg):
... return type("Enum", (object,), dict(zip(posarg, xrange(len(posarg))), **
keysarg))
...
>>> Seasons = enum("Spring","Summer","Autumn",Winter=1)
>>> Seasons.Spring
0
>>> Seasons = namedtuple('Seasons','Spring Summer Autumn Winter')._make(range(4))
>>> print Seasons.Spring
0
Python中枚举的替代实现方式远不止上述这些,在此就不一一列举了。那么,既然枚举在Python中有替代的实现方式,为什么人们还要执着地提出各自建议要求语言实现枚举呢?显然,这些替代实现有其不合理的地方。
- 允许枚举值重复。我们以collections.namedtuple为例,下面的例子中枚举值Spring与Autumn相等,但却不会提示任何错误。
>>> Seasons._replace(Spring =2)
Seasons(Spring=2, Summter=1, Autumn=2, Winter=3) #Spring和Autumn的值相等,都为2
- 支持无意义的操作。
>>> Seasons.Summer+Seasons.Autumn == Seasons.Winter
True #Seasons.Summer+Seasons.Autumn 相加无任何实际意义
实际上Python2.7以后的版本还有另外一种替代选择——使用第三方模块flufl.enum
,它包含两种枚举类:一种是Enum,只要保证枚举值唯一即可,对值的类型没限制;还有一种是IntEnum,其枚举值为int型。
>>> from flufl.enum import Enum
>>> class Seasons(Enum): #
#继承自Enum定义枚举
... Spring ="Spring"
... Summer = 2
... Autumn = 3
... Winter = 4
...
>>> Seasons = Enum('Seasons', 'Spring Sumter Autumn Winter')
flufl.enum
提供了__members__
属性,可以对枚举名称进行迭代。
>>> for member in Seasons.__members__:
... print member
...
Spring
Summer
Autumn
Winter
可以直接使用value属性获取枚举元素的值,如:
>>> print Seasons.Summer.value
2
flufl.enum不支持枚举元素的比较。
>>> Seasons.Summer <Seasons.Autumn #flufl.enum不支持无意义的操作
Traceback (most recent call last):
... ...
raise NotImplementedError
NotImplementedError
更多关于flufl.enum
的使用可以参考网页http://Pythonhosted.org/flufl.enum/docs/using.html
的内容。
值得一提的是,Python3.4中根据PEP435的建议终于加入了枚举Enum,其实现主要参考实现flufl.enum
,但两者之间还是存在一些差别,如flufl.enum允许枚举继承,而Enum仅在父类没有任何枚举成员的时候才允许继承等,读者可以仔细阅读PEP435了解更多详情。另外,如果要在Python3.4之前的版本中使用枚举Enum,可以安装Enum的向后兼容包enum34,下载地址为https://pypi.Python.org/pypi/enum34
。
酷客网相关文章:
评论前必须登录!
注册