Python中枚举类型的常见做法是什么?

153

我该如何在Python中实现一个枚举类型(在一些编程语言中拼写为enum)?获取此功能的常见做法是什么?


18
现在Python 3.4中有一个标准的枚举类型。请阅读此帖子:https://dev59.com/iGQn5IYBdhLWcg3wrouL - Javier
4
这是现在Python中的枚举类型的PEP:https://www.python.org/dev/peps/pep-0435/ - shuttle87
4个回答

374
class Materials:
    Shaded, Shiny, Transparent, Matte = range(4)

>>> print Materials.Matte
3

更新:针对 Python 3.4+:

从 Python 3.4+ 开始,你可以使用 enum 模块中的 Enum(或者带有 int 值的枚举类型可以用 IntEnum)来定义枚举类型。使用 enum.auto 可以自动递增枚举值:

import enum


class Materials(enum.IntEnum):
    Shaded = 1
    Shiny = enum.auto()
    Transparent = 3
    Matte = enum.auto()


print(Materials.Shiny == 2)  # True
print(Materials.Matte == 4)  # True

17
我之前没看过这个,不错的东西。 - Ben Blank
4
你可以使用“_unused,Shaded,Shiny,Transparent,Matte = range(5)”这行代码。 - zekel
83
有点晚了,但如果你不喜欢有“_unused”,也可以使用“Shaded,Shiny,Transparent,Matte = range(1,5)”。 - Davy8
4
很遗憾,这种枚举的方法是不完整的,因为无法对枚举进行迭代,并且每个值都不是唯一的类型(例如,只是 int)。 - Gewthen
9
请更新此内容以添加说明“enums”自Python 3.4版本起可用。 - SudoKid
显示剩余5条评论

21

我已经多次看到这个模式:

>>> class Enumeration(object):
        def __init__(self, names):  # or *names, with no .split()
            for number, name in enumerate(names.split()):
                setattr(self, name, number)

>>> foo = Enumeration("bar baz quux")
>>> foo.quux
2

您也可以直接使用类成员,不过您需要自己提供编号:

>>> class Foo(object):
        bar  = 0
        baz  = 1
        quux = 2

>>> Foo.quux
2

如果你正在寻找更为强大的功能(支持稀疏值、特定枚举类型的异常等),可以尝试这个代码示例


9

我不知道为什么 Python 没有原生支持枚举类型。我找到的最好的模拟方法是通过覆盖 _ str _ 和 _ eq _ 来实现,这样你可以比较它们,在使用 print() 时可以获得字符串而不是数值。

class enumSeason():
    Spring = 0
    Summer = 1
    Fall = 2
    Winter = 3
    def __init__(self, Type):
        self.value = Type
    def __str__(self):
        if self.value == enumSeason.Spring:
            return 'Spring'
        if self.value == enumSeason.Summer:
            return 'Summer'
        if self.value == enumSeason.Fall:
            return 'Fall'
        if self.value == enumSeason.Winter:
            return 'Winter'
    def __eq__(self,y):
       return self.value==y.value

用法:

>>> s = enumSeason(enumSeason.Spring)

>>> print(s)

Spring

4
PEP354已经被否决。请访问http://www.python.org/dev/peps/pep-0354/#rejection-notice。 - Fred Larson
4
使用一个类字典{"Spring": 0, "Summer":1, ...}并在__init__中遍历条目并设置属性会更快,因为这样__str__只需查找相应的值而不必手动编写每种情况的代码。 - Charles J. Daniels
2
请查看此链接:https://www.python.org/dev/peps/pep-0435/。 - shuttle87

6
你可以使用继承结构,尽管我用得越多,感觉越不舒服。
class AnimalEnum:
  @classmethod
  def verify(cls, other):
    return issubclass(other.__class__, cls)


class Dog(AnimalEnum):
  pass

def do_something(thing_that_should_be_an_enum):
  if not AnimalEnum.verify(thing_that_should_be_an_enum):
    raise OhGodWhy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接