2

I would like to define a set of flags (subclassed from enum.Flag), with some flags which are defined based on others. This is similar to the white flag in the example: https://docs.python.org/3/library/enum.html#flag, but it is not just a combinations of previous flags, but needs its own value too.

My first attempt was:

from enum import Flag, auto
class MyFlag(Flag):
    NONE = 0
    DEFAULT = auto()
    FIRST = auto() | DEFAULT
    SECOND = auto() | DEFAULT
    THIRD = auto()
    ANY = FIRST | SECOND | THIRD

But this raised an error: TypeError: unsupported operand type(s) for |: 'auto' and 'int'

The working implementation should give:

>>> print(bool(MyFlag.FIRST & MyFlag.DEFAULT))
# prints True
>>> print(bool(MyFlag.THIRD & MyFlag.DEFAULT))
# prints False
markmuetz
  • 9,334
  • 2
  • 32
  • 33

3 Answers3

2

The auto() object in aenum1 is much more robust:

from aenum import Flag, auto

class MyFlag(Flag):
    NONE = 0
    DEFAULT = auto()
    FIRST = auto() | DEFAULT
    SECOND = auto() | DEFAULT
    THIRD = auto()
    ANY = FIRST | SECOND | THIRD

and in use:

>>> list(MyFlag)
[
    <MyFlag.NONE: 0>,
    <MyFlag.DEFAULT: 1>,
    <MyFlag.FIRST: 3>,
    <MyFlag.SECOND: 5>,
    <MyFlag.THIRD: 8>,
    <MyFlag.ANY: 15>,
    ]

1 Disclosure: I am the author of the Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) library.

Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
  • That looks exactly like how I imagined the code should be written. I'll check out aenum. Thanks. – markmuetz Mar 11 '20 at 22:41
  • Awesome!! Great job for `aenum`! It actually makes you wonder why `ANY = FIRST | SECOND | THIRD` is not part of `stdlib.enum` by default :) – Jean-Francois T. May 22 '23 at 02:45
1

Note that if you don't need to do auto() | DEFAULT, the rest works fine out of the box:

from enum import Flag, auto

class MyFlag(Flag):
    NONE = 0
    DEFAULT = auto()
    FIRST = auto()
    SECOND = auto()
    THIRD = auto()
    ANY = FIRST | SECOND | THIRD

And we would have

>>> [
...    MyFlag.NONE,
...    MyFlag.DEFAULT,
...    MyFlag.FIRST,
...    MyFlag.SECOND,
...    MyFlag.THIRD,
...    MyFlag.ANY,
...    MyFlag.FIRST | MyFlag.SECOND,
...    MyFlag.FIRST | MyFlag.SECOND | MyFlag.THIRD,
... ]
[<MyFlag.NONE: 0>,
 <MyFlag.DEFAULT: 1>,
 <MyFlag.FIRST: 2>,
 <MyFlag.SECOND: 4>,
 <MyFlag.THIRD: 8>,
 <MyFlag.ANY: 14>,
 <MyFlag.SECOND|FIRST: 6>,
 <MyFlag.ANY: 14>]

This works as well with enum.IntFlag.

Jean-Francois T.
  • 11,549
  • 7
  • 68
  • 107
-1

The following works, by defining a hidden member of the MyFlag class.

from enum import Flag, auto
class MyFlag(Flag):
    NONE = 0
    DEFAULT = auto()
    _FIRST = auto()
    FIRST = _FIRST | DEFAULT
    _SECOND = auto()
    SECOND = _SECOND | DEFAULT
    THIRD = auto()
    ANY = FIRST | SECOND | THIRD
markmuetz
  • 9,334
  • 2
  • 32
  • 33