gpt4 book ai didi

python - Flag 枚举中所有值的表示

转载 作者:太空狗 更新时间:2023-10-29 17:17:10 26 4
gpt4 key购买 nike

我想在我的 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 或更高版本有关。

最佳答案

有几种方法可以解决这个问题:


使用类属性方法需要注意的一件事是,由于描述符是在类而不是元类上定义的,因此不存在针对设置和删除的通常保护措施——换句话说:

>>> 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com