如何在内部跟踪Python枚举值?

时间:2018-10-29 08:05:58

标签: python python-3.x enums

我的最终目标确实是在我的Enum类中创建一个辅助方法,该方法始终返回Enum成员,并且从不抛出异常,给定任何可能的值,例如

Color.from_value('red')

如果该值不属于枚举,则helper方法将返回默认值,例如Color.UNKNOWN

基于此answer from another related question,我可以通过一些内置成员列出这些值来进行检查。但是,我接下来要做的是跟踪内部成员中的所有值,这样就不必每次调用helper方法时都始终迭代这些值。我尝试做类似以下的事情:

class Color(Enum):
    RED = 'red'
    BLUE = 'blue'
    GREEN = 'green'

    # this doesn't work
    _values = [item.value for item in Color]

,并且按预期,它不起作用。这也许是Python枚举中已内置的东西吗?

3 个答案:

答案 0 :(得分:3)

您可以创建方法并检查类中的值:

import enum

class Color(enum.Enum):
    RED = 'red'
    BLUE = 'blue'
    GREEN = 'green'
    UNKNOWN = "unknown"

    @classmethod
    def from_value(cls, value):
      try:
        return {item.value: item for item in cls}[value]
      except KeyError:
        return cls.UNKNOWN

print(Color.from_value("hey"))
print(Color.from_value("red"))

结果:

Color.UNKNOWN
Color.RED

您在这里有一个live example

如果您不想重复,可以始终在外部缓存值:

class Color(enum.Enum):
    RED = 'red'
    BLUE = 'blue'
    GREEN = 'green'
    UNKNOWN = "unknown"

    @classmethod
    def from_value(cls, value):
      try:
        return _COLORITEMS[value]
      except KeyError:
        return cls.UNKNOWN
_COLORITEMS = {item.value: item for item in Color}

答案 1 :(得分:0)

此后,我已经接受Netwave's answer,但我将其添加为与原始版本有所不同。我想保留答案,以供参考。

import enum

class Color(enum.Enum):
    RED = 'red'
    BLUE = 'blue'
    GREEN = 'green'
    UNKNOWN = "unknown"

    @staticmethod
    def from_value(value):
      try:
        return Color(value)
      except ValueError:
        return cls.UNKNOWN

请注意,由于不再需要@classmethod参数,因此我已将@staticmethod更改为cls。另外,我在这里处理ValueError而不是KeyError,因为如果找不到值,这就是Color()引发的问题。这也适用于多值/元组枚举。

第二种方法:

import enum

class Color(enum.Enum):
    RED = 'red'
    BLUE = 'blue'
    GREEN = 'green'
    UNKNOWN = "unknown"

    @staticmethod
    def from_value(value):
        return Color(value) if value in _COLORITEMS else Color.UNKNOWN

_COLORITEMS = [item.value for item in Color]

在这里,我从字典切换到列表以跟踪值。我只是检查该值是否在列表中,而不是处理KeyError。我本可以使用一个集合,但是由于它是一个枚举,因此保证值是唯一的(如果我理解正确的话)。

答案 2 :(得分:0)

[摘自my answer here]

使用Python 3.6(和aenum 2.0 1 ),您可以指定一个_missing_方法,该方法将在提高ValueError之前为您的班级提供最后的机会。现在,您可以这样做:

    @classmethod
    def _missing_(cls, name):
        return cls.never_heard_of

NB None仅应返回枚举成员或_missing_-如果{{ 1}}。


1 披露:我是Python stdlib Enumenum34 backportAdvanced Enumeration (aenum)库的作者。