>>> from env_helper import info; info()
页面更新时间: 2023-12-27 09:11:55
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-16-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

2.4. 理解枚举替代实现的缺陷

关于枚举最经典的例子大概非季节和星期莫属了,它能够以更接近自然语言的方式来表 达数据, 使得程序的可读性和可维护性大大提高。然而, 很不幸,也许你习惯了其他语言中的枚举类型,但在Python3.4以前却并不提供。 关于要不要加入枚举类型的问题就引起了不少讨论, 在PEP354中曾提出增加枚举的建议,但被拒绝。 于是人们充分利用Python的动态性这个特征,想出了枚举的各种替代实现方式。

2.4.1. 使用类属性

>>> class Seasons:
>>>     Spring=0
>>>     Summer= 1
>>>     Autumn=2
>>>     Winter= 3
>>> print (Seasons.Spring)
0

上面的例子可以直接简化为:

>>> class Seasons:
>>>     Spring,Summer,Autumn,Winter=range(4)

2.4.2. 借助函数

>>> def enum (*posarg, **keysarg):
>>>     return type("Enum", (object,), dict(zip(posarg, range(len(posarg))), ** keysarg))
>>> Seasons = enum ("Spring", "Summer", "Autumn", Winter=1)
>>> Seasons.Spring
0

2.4.3. 使用 collections.namedtuple

>>> import collections
>>> Seasons = collections.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, Sunimter=1, Autumn=2, Winter=3) #Spring 和 Autumn 的值相等,部为 2

  • 支持无意义的操作。

>>> Seasons.Summer+Seasons.Autumn ==Seasons .Winter #相加无意义
True

2.4.4. 使用第三方模块 flufl.emim

实际上Python2.7以后的版本还有另外一种替代选择——使用第三方模块 flufl.emim , 它包含两种枚举类:一种是 Enum ,只要保证枚举值唯一即可,对值的类型没限制; 还有一种是 IntEnum ,其枚举值为 int 型。 这个包需要单独安装:

sudo apt install python3-flufl.enum

>>> from flufl.enum import Enum
>>> class Seasons(Enum) :
>>>     '''
>>>     继承自 Enum 走义枚举
>>>     '''
>>>     Spring="Spring"
>>>     Summer=2
>>>     Autumn=3
>>>     Winter=4
>>> Seasons = Enum('Seasons','Spring Summer Autumn Winter')

flufl.enum提供了 _members_ 属性,可以对枚举名称进行迭代。

>>> Seasons.mro()
[<Seasons {Autumn: 3, Spring: 1, Summer: 2, Winter: 4}>, <Enum {}>, object]
>>> dir(Seasons)
['Autumn', 'Spring', 'Summer', 'Winter']
>>> for member in Seasons:
>>>     print(member)
Seasons.Autumn
Seasons.Spring
Seasons.Summer
Seasons.Winter

可以直接使用value属性获取枚举元素的值,如:

>>> print (Seasons.Summer.value)
2

flufl.enum不支持枚举元素的比较。

Seasons. Summer <Seasons. Autumn#不支持无SX 的操作

更多关于 flufl.enum 的使用可以参考网页 http://Pythonhosted.org/flufl.enurnVdocs/using.html 的内容。

值得一提的是,Python3.4中根据PEP435的建议终于加入了枚举Enum 。 其实现主要 参考实现 flufi.enumt 但两者之间还是存在一些差别, 如flufl.enum允许枚举继承,而Enum 仅在父类没有任何枚举成员的时候才允许继承等。 读者可以仔细阅读PEP435 了解更多详 情。

另外,如果要在Python3.4之前的版本中使用枚举Enum , 可以安装Enum的向后兼容包 errum34,下载地址为 https://pypi.Python.org/pypi/emim34l