There are a few ways to overcome this issue:
One thing to be aware of with the class property method is since the descriptor is defined on the class and not the metaclass the usual protections against setting and deleting are absent -- in other words:
>>> RefreshFlags.ALL
<RefreshFlags.DEFENSES|BUILDINGS|RESOURCES|EVENTS: 15>
>>> RefreshFlags.ALL = 'oops'
>>> RefreshFlags.ALL
'oops'
Creating a new base class:
# 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
And in use:
class RefreshFlag(AllFlag):
EVENTS = auto()
RESOURCES = auto()
BUILDINGS = auto()
DEFENSES = auto()
>>> RefreshFlag.ALL
<RefreshFlag.DEFENSES|BUILDINGS|RESOURCES|EVENTS: 15>
The interesting difference in the ALL
property is the setting of the name in _member_map_
-- this allows the same protections afforded to Enum members:
>>> RefreshFlag.ALL = 9
Traceback (most recent call last):
....
AttributeError: Cannot reassign members.
However, there is a race condition here: if RefreshFlag.ALL = ...
occurs before RefreshFlag.ALL
is activated the first time then it is clobbered; for this reason I would use a decorator in this instance, as the decorator will process the Enum before it can be clobbered.
# 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
And in use:
@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>
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…