这个问题的答案类似于Adding NONE and ALL to Flag Enums 的答案(请随意查看那里的深入解释;注意:该答案使用类类型的装饰器,而下面是一个函数-type 装饰器)。
def add_invalid(enumeration):
"""
add INVALID psuedo-member to enumeration with value of -1
"""
#
member = int.__new__(enumeration, -1)
member._name_ = 'INVALID'
member._value_ = -1
enumeration._member_map_['INVALID'] = member
enumeration._value2member_map_[-1] = member
return enumeration
看起来像
@add_invalid
class Level(IntEnum):
DEFAULTS = 0
PROJECT = 1
MASTER = 2
COLLECT = 3
OBJECT = 4
并在使用中:
>>> list(Level)
[<Level.DEFAULTS: 0>, <Level.PROJECT: 1>, <Level.MASTER: 2>, <Level.COLLECT: 3>, <Level.OBJECT: 4>]
>>> type(Level.INVALID)
<enum 'Level'>
>>> Level.INVALID
<Level.INVALID: -1>
>>> Level(-1)
<Level.INVALID: -1>
>>> Level['INVALID']
<Level.INVALID: -1>
此方法有几个注意事项:
- 它使用的内部枚举结构可能会在未来发生变化
- INVALID,虽然没有正常显示,但在其他方面是
Enum 成员(因此无法更改、删除等)
如果您不想使用内部结构,和/或您实际上不需要 INVALID 成为 Enum 成员,则可以改用 Constant 类 found here:
class Constant:
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 Level(IntEnum):
#
DEFAULTS = 0
PROJECT = 1
MASTER = 2
COLLECT = 3
OBJECT = 4
#
INVALID = Constant(-1)
并在使用中:
>>> Level.INVALID
-1
>>> type(Level.INVALID)
<class 'int'>
>>> list(Level)
[<Level.DEFAULTS: 0>, <Level.PROJECT: 1>, <Level.MASTER: 2>, <Level.COLLECT: 3>, <Level.OBJECT: 4>]
使用自定义描述符的缺点是它可以在类上进行更改;你可以通过使用aenum1 及其内置的constant 类(NB:小写)来解决这个问题:
from aenum import IntEnum, constant
class Level(IntEnum):
#
DEFAULTS = 0
PROJECT = 1
MASTER = 2
COLLECT = 3
OBJECT = 4
#
INVALID = constant(-1)
并在使用中:
>>> Level.INVALID
-1
>>> Level.INVALID = None
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/ethan/.local/lib/python3.6/site-packages/aenum/__init__.py", line 2128, in __setattr__
'%s: cannot rebind constant %r' % (cls.__name__, name),
AttributeError: Level: cannot rebind constant 'INVALID'
1 披露:我是Python stdlib Enum、enum34 backport 和Advanced Enumeration (aenum) 库的作者。