您可以在内部跟踪值,但这有点麻烦:
尝试 1
_values = [k for k in vars().keys() if not k.startswith('_')]
问题 1
>>> # _values is a member
>>> Color._values
<Color._huh: ['RED', 'BLUE', 'GREEN']>
尝试 2
使用来自this answer的Constant
_values = Constant([k for k in vars().keys() if not k.startswith('_')])
问题 2
它并不是真正恒定的,因为您仍然可以附加到列表中——但这可以通过转换为 tuple 来解决:
_values = Constant(tuple([k for k in vars().keys() if not k.startswith('_')]))
但是,这仍然不能解决UNKNOWN 的问题。
解决方案
使用 Python 3.6 或 aenum 2.01,您可以指定一个 _missing_ 方法,该方法将被调用以在引发 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
或
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())
注意:只有枚举成员或 None 应该由 _missing_ 返回——如果返回任何其他内容,以后的 Python 版本将引发 TypeError。
1 披露:我是Python stdlib Enum、enum34 backport 和Advanced Enumeration (aenum) 库的作者。