Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在内部跟踪Python枚举值?_Python_Python 3.x_Enums - Fatal编程技术网

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

如何在内部跟踪Python枚举值?,python,python-3.x,enums,Python,Python 3.x,Enums,我的最终目标实际上是在我的Enum类中创建一个helper方法,该方法总是返回一个Enum成员,并且在给定任何可能的值(例如 Color.from_value('red') 如果该值不是枚举的一部分,则helper方法将返回默认值,例如Color.UNKNOWN 基于此,我可以通过一些内置成员列出这些值来检查这些值。但是,我接下来要做的是跟踪内部成员中的所有值,这样我就不必每次调用helper方法时都遍历这些值。我试着做了如下类似的事情: class Color(Enum): RED

我的最终目标实际上是在我的Enum类中创建一个helper方法,该方法总是返回一个Enum成员,并且在给定任何可能的值(例如

Color.from_value('red')
如果该值不是枚举的一部分,则helper方法将返回默认值,例如
Color.UNKNOWN

基于此,我可以通过一些内置成员列出这些值来检查这些值。但是,我接下来要做的是跟踪内部成员中的所有值,这样我就不必每次调用helper方法时都遍历这些值。我试着做了如下类似的事情:

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

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

正如所料,它不起作用。这可能是Python枚举中内置的吗?

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

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
给你一个

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

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}
我已经接受了,但我添加了这一点作为一个从原来的变化。我想保留答案作为参考

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]

在这里,我从dict切换到list来跟踪值。我没有处理
KeyError
,而是简单地检查该值是否在列表中。我本可以使用集合,但因为它是枚举,所以值保证是唯一的(如果我理解正确)。

您可以在内部跟踪值,但这有点麻烦:

尝试1

问题1

问题2

它实际上不是常量,因为您仍然可以附加到列表中——但这可以通过强制转换到
tuple
来解决:

_values = Constant(tuple([k for k in vars().keys() if not k.startswith('_')]))
然而,这仍然不能解决
未知的问题

解决方案

使用Python 3.6或1,您可以指定一个
\u missing\u
方法,该方法将被调用,以便在引发
ValueError
之前为类提供最后一次机会:

class Constant:  # use Constant(object) if in Python 2
    def __init__(self, value):
        self.value = value
    def __get__(self, *args):
        return self.value
    def __repr__(self):
        return '%s(%r)' % (self.__class__.__name__, self.value)


class Color(Enum):

    RED = 'red'
    BLUE = 'blue'
    GREEN = 'green'
    UNKNOWN = 'unknown'
    _values = Constant(tuple([k for k in vars().keys() if not k.startswith('_')]))

    @classmethod
    def _missing_(cls, name):
        if name.lower() in cls._values:
            return cls(name.lower())
        else:
            return cls.UNKNOWN

注意:
\u missing.
只应返回枚举成员或
——如果返回任何其他内容,则稍后的Python版本将引发
类型错误



1披露:我是、和库的作者。

那么如果有人调用
Color.from_value('chucknorris')
,会发生什么?这会创建一个新的枚举值并返回它吗?不会。它将返回一个默认枚举,类似于
Color.UNKNOWN
.ha!我正要提出第二种变体。但是你更快!因此,从技术上讲,无法在内部跟踪枚举类中的值?@PsychoPunch,我不知道如何跟踪,因为在完全读取之前,您无法访问类值(AFAIK)。谢谢,但我不确定您为什么将其标记为重复,因为我的问题实际上是关于其他内容。虽然您的解决方案可能同时适用于这两种情况,而且这些问题相互交叉,但它们并不完全相同。请看,我还有一个要求,即
from_value
不区分大小写,以便
from_value('red')
from_value('red')
返回
Color.red
。我如何通过使用
\u missing\u
来实现这一点?
classmethod
在这里是更好的选择,因为该方法实际上需要类才能正常工作。通过直接指定类名,您可以避开这个问题,但一旦更改名称
颜色
,这将失败。使用
静态方法
会产生误导。
_values = Constant([k for k in vars().keys() if not k.startswith('_')])
_values = Constant(tuple([k for k in vars().keys() if not k.startswith('_')]))
class Constant:  # use Constant(object) if in Python 2
    def __init__(self, value):
        self.value = value
    def __get__(self, *args):
        return self.value
    def __repr__(self):
        return '%s(%r)' % (self.__class__.__name__, self.value)


class Color(Enum):

    RED = 'red'
    BLUE = 'blue'
    GREEN = 'green'
    UNKNOWN = 'unknown'
    _values = Constant(tuple([k for k in vars().keys() if not k.startswith('_')]))

    @classmethod
    def _missing_(cls, name):
        if name.lower() in cls._values:
            return cls(name.lower())
        else:
            return cls.UNKNOWN
class Color(Enum):

    RED = 'red'
    BLUE = 'blue'
    GREEN = 'green'
    UNKNOWN = 'unknown'

    @classmethod
    def _missing_(cls, name):
        if name == name.lower():
            # avoid infinite recursion
            return cls.UNKNOWN
        else:
            return cls(name.lower())