Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

157
Views
Representation of all values in Flag enum

I would like to have a "ALL" flag in my python Flags enum for which

myenum.EVERY_MEMBER & myenum.ALL == myenum.EVERY_MEMBER

holds true. I currently have:

from enum import Flag, auto

class RefreshFlags(Flag):
    NONE = 0
    EVENTS = auto()
    RESOURCES = auto()
    BUILDINGS = auto()
    DEFENSES = auto()
    .....

Because this enum might grow at any state of development I would like to have something like

@property
def ALL(self):
    retval = self.NONE
    for member in self.__members__.values():
        retval |= member
    return retval

This does not work:

RefreshFlags.EVENTS  & RefreshFlags.ALL

TypeError: unsupported operand type(s) for &: 'RefreshFlags' and 'property'

Please note that this question currently only relates to python 3.6 or later.

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

There are a few ways to overcome this issue:

  • use a classproperty (see Zero's answer)

  • use a class decorator (see MSeifert's answer)

  • use a mixin (currently buggy)

  • create a new base class (see below)


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>
over 4 years ago · Santiago Trujillo Report

0

TL;DR Because property is only evaluated on instances of a class while the __members__ is only accessible on the class.


If you access a property on a class it just returns a property:

>>> RefreshFlags.ALL
<property at 0x2a5d93382c8>

To make this work however you need to either make it a classmethod:

from enum import Flag, auto

class RefreshFlags(Flag):
    NONE = 0
    EVENTS = auto()
    RESOURCES = auto()
    BUILDINGS = auto()
    DEFENSES = auto()

    @classmethod
    def ALL(cls):
        retval = self.NONE
        for member in cls.__members__.values():
            retval |= member
        return retval

>>> RefreshFlags.ALL()
<RefreshFlags.DEFENSES|BUILDINGS|RESOURCES|EVENTS: 15>

or access the property on an instance:

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
        # One needs to access .__class__ here!
        for member in self.__class__.__members__.values():
            retval |= member
        return retval

>>> RefreshFlags.EVENTS.ALL
<RefreshFlags.DEFENSES|BUILDINGS|RESOURCES|EVENTS: 15>

In both cases you can do your comparison later:

>>> RefreshFlags.EVENTS & RefreshFlags.EVENTS.ALL
<RefreshFlags.EVENTS: 1>

You stated in the comments that you want the ALL member to behave like the others, in that case I suggest using a class decorator:

def with_ALL_member(enumeration):
    retval = enumeration(0)  # in case NONE is not defined
    for name, member in enumeration.__members__.items():
        retval |= member
    enumeration.ALL = retval
    return enumeration

@with_ALL_member
class RefreshFlags(Flag):
    NONE = 0
    EVENTS = auto()
    RESOURCES = auto()
    BUILDINGS = auto()
    DEFENSES = auto()

>>> RefreshFlags.EVENTS & RefreshFlags.ALL
<RefreshFlags.EVENTS: 1>

>>> RefreshFlags.DEFENSES & RefreshFlags.ALL
<RefreshFlags.DEFENSES: 8>

The class decorator can also be used on other enums :)

over 4 years ago · Santiago Trujillo Report

0

Following up on MSeifert's answer, it's possible to write a @classproperty decorator which allows you to access RefreshFlags.ALL directly as a property (rather than as a conventional method or a property on an instance):

from enum import Flag, auto
from operator import or_
from functools import reduce


class classproperty:

    def __init__(self, func):
        self._func = func

    def __get__(self, obj, owner):
        return self._func(owner)


class RefreshFlags(Flag):

    NONE = 0
    EVENTS = auto()
    RESOURCES = auto()
    BUILDINGS = auto()
    DEFENSES = auto()

    @classproperty
    def ALL(cls):
        return reduce(or_, cls)

You can of course write ALL() with an explicit for loop as in your example; the above is merely offered as an alternative.

>>> RefreshFlags.ALL
<RefreshFlags.DEFENSES|BUILDINGS|RESOURCES|EVENTS: 15>
>>> RefreshFlags.ALL & RefreshFlags.BUILDINGS
<RefreshFlags.BUILDINGS: 4>
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!