没有枚举的Pythonic设计

时间:2012-10-10 02:07:13

标签: python enums

关于如何在Python中实现枚举,有一些问题。大多数解决方案最终或多或少等同于以下内容:

class Animal:
    DOG=1
    CAT=2

其他人已经提出了构建枚举的更复杂的方法,但最终看起来像这个例子的时候看起来就像这样。

根据我在Java和C#的经验,我可以想到这种习语的各种用法。但是,它似乎不是非常Pythonic。事实上,似乎每当有人问到为什么Python中没有枚举时,你会倾向于对如何没有理由尝试在Python这样的语言中强制编译时类型安全性的罐装响应感到呻吟,或者如何需要枚举的设计在Python中是难闻的气味。

我的问题不是如何在Python中实现枚举,而是一般人们如何解决以Pythonic方式使用枚举的问题的解决方案。换句话说,如果不将Java / C#解决方案移植到Python,您将如何解决一个问题,该问题有助于拥有一组具有离散可能值的数据类型。

4 个答案:

答案 0 :(得分:4)

PEP 435刚被接受,它将枚举包与Enum类和其他衍生物(如IntEnum)一起添加到标准库中。这意味着从Python 3.4开始,在设计中使用枚举的“pythonic”方法就是使用这个包。它看起来像这样:

>>> from enum import Enum
>>> class Color(Enum):
...    red = 1
...    green = 2
...    blue = 3

>>> print(Color.red)
Color.red

>>> print(Color.red.name)
red

>>>> for color in Color:
....     print(color)
Color.red
Color.green
Color.blue

这种设计的关键特性是键可以拒绝比较它没有意义(与其他答案中建议的字符串键不同),允许键具有与键值无关的漂亮打印,以及给出通过在Enum子类上定义方法来键值特殊属性,以及在用户尝试使用Enum类中的非法键时抛出显式且可理解的错误的属性。

答案 1 :(得分:3)

由于Python字符串是不可变的(并且Python会在必要时对它们进行实习),因此对于使用数字枚举来说,并不具有特定的优势。相反,您可以简单地使用frozensettuple字符串(取决于您是否关心订购)。

另一方面,如果你关心的是命名空间,那么使一个类的属性工作得很好。

正如评论中所提到的,如果你正在寻找像状态机实现这样的东西,那么一流的功能就是你的朋友。

答案 2 :(得分:2)

如果没有来自C#或Java背景,我仍然不太了解这种对枚举的兴趣。

根据我的理解,我可能会回到django风格,在设置文件中放置任何必要的常量并在必要时导入。

settings.py/animals.py

DOG = 1
CAT = 2

其他档案:

from animals import CAT, DOG

甚至......

settings.py

ANIMALS = { "DOG": 1, "CAT": 2}

其他档案:

from settings import ANIMALS

my_animal = "FROG"
if my_animal not in ANIMALS.keys():
    print "new species discovered!"

答案 3 :(得分:-1)

我不相信C#中的Enums。对于State-Machine,您有策略模式。而不是查看对象的状态并决定做什么。封装在对象本身中做什么的逻辑。

这是Python中的一种自然方法,向我介绍枚举只是鼓励不良代码。