我想在我的 python Flags 枚举中有一个“ALL”标志
myenum.EVERY_MEMBER & myenum.ALL == myenum.EVERY_MEMBER
成立。我目前有:
from enum import Flag, auto
class RefreshFlags(Flag):
NONE = 0
EVENTS = auto()
RESOURCES = auto()
BUILDINGS = auto()
DEFENSES = auto()
.....
因为这个枚举可能会在任何开发状态下增长,所以我想要类似的东西
@property
def ALL(self):
retval = self.NONE
for member in self.__members__.values():
retval |= member
return retval
这不起作用:
RefreshFlags.EVENTS & RefreshFlags.ALL
TypeError: unsupported operand type(s) for &: 'RefreshFlags' and 'property'
请注意,此问题目前仅与 python 3.6 或更高版本有关。
最佳答案
有几种方法可以解决这个问题:
使用
classproperty
(参见Zero's answer
)使用类装饰器(参见
MSeifert's answer
)使用混音 (
currently buggy
)创建一个新的基类(见下文)
使用类属性方法需要注意的一件事是,由于描述符是在类而不是元类上定义的,因此不存在针对设置和删除的通常保护措施——换句话说:
>>> RefreshFlags.ALL
<RefreshFlags.DEFENSES|BUILDINGS|RESOURCES|EVENTS: 15>
>>> RefreshFlags.ALL = 'oops'
>>> RefreshFlags.ALL
'oops'
创建一个新的基类:
# lightly tested
from enum import Flag, auto
from operator import or_ as _or_
from functools import reduce
class AllFlag(Flag):
@classproperty
def ALL(cls):
cls_name = cls.__name__
if not len(cls):
raise AttributeError('empty %s does not have an ALL value' % cls_name)
value = cls(reduce(_or_, cls))
cls._member_map_['ALL'] = value
return value
并在使用中:
class RefreshFlag(AllFlag):
EVENTS = auto()
RESOURCES = auto()
BUILDINGS = auto()
DEFENSES = auto()
>>> RefreshFlag.ALL
<RefreshFlag.DEFENSES|BUILDINGS|RESOURCES|EVENTS: 15>
ALL
属性中有趣的区别在于 _member_map_
中名称的设置——这允许为 Enum 成员提供相同的保护:
>>> RefreshFlag.ALL = 9
Traceback (most recent call last):
....
AttributeError: Cannot reassign members.
但是,这里有一个竞争条件:如果 RefreshFlag.ALL = ...
发生在 RefreshFlag.ALL
被激活的第一个时间然后它被破坏了;出于这个原因,我会在这种情况下使用装饰器,因为装饰器会在 Enum 被破坏之前对其进行处理。
# lightly tested
from enum import Flag, auto
from operator import or_ as _or_
from functools import reduce
def with_limits(enumeration):
"add NONE and ALL psuedo-members to enumeration"
none_mbr = enumeration(0)
all_mbr = enumeration(reduce(_or_, enumeration))
enumeration._member_map_['NONE'] = none_mbr
enumeration._member_map_['ALL'] = all_mbr
return enumeration
并在使用中:
@with_limits
class RefreshFlag(Flag):
EVENTS = auto()
RESOURCES = auto()
BUILDINGS = auto()
DEFENSES = auto()
>>> RefreshFlag.ALL = 99
Traceback (most recent call last):
...
AttributeError: Cannot reassign members.
>>> RefreshFlag.ALL
<RefreshFlag.DEFENSES|BUILDINGS|RESOURCES|EVENTS: 15>
>>> RefreshFlag.NONE
<RefreshFlag.0: 0>
关于python - Flag 枚举中所有值的表示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42251081/