You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Iterating over enum.Flag types ignores zero-valued in Python 3.11 #109633
In Python 3.11, the same is true for enum.Enum types, but the behavior seems to have changed for enum.Flag types. Now, iterating over the type only yields its nonzero values.
It is more accurate to say that Enum and Flag iterate over the canonical values. For example:
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
ROJO = 1
VERDE = 2
AZUL = 3
list(Color)
# RED, GREEN, BLUE
class BlendColor(Flag):
BLACK = 0
RED = 1
GREEN = 2
BLUE = 4
WHITE = RED | GREEN | BLUE
list(BlendColor)
# RED, GREEN, BLUE
Aliases have always been omitted from iteration, and flag values with no, or more than one, bit(s) set are considered aliases since Python 3.11 -- this was considered a bug-fix.
Oh I see. Thanks for the clarification, @ethanfurman.
Looking back over the docs now, they do pretty much convey everything that you've explained here, although some of the details are subtle. The only thing that I think isn't explicitly explained there is that zero-valued flags are considered aliases.
I do have a use case where I need both alias and elements of a flag. Is there a way to explicitly iterate over either only elements and only aliases that works in both old AND new version?
Activity
CharlieZhao95 commentedon Sep 21, 2023
I bisected to here:
sobolevn commentedon Sep 21, 2023
From the docs, I can say that now
0is treated as more like a special value:https://docs.python.org/3/library/enum.html#enum.Flag
Check how
<Color: 0>is used all over the place.The technical reason behind this is that now
0does not get into_member_names_here:cpython/Lib/enum.py
Lines 313 to 319 in 712cb17
Because
0is not a_is_single_bitmember (it is explicit):cpython/Lib/enum.py
Lines 93 to 98 in 712cb17
So, when we use
__iter__over_member_names_zero-value is not there:cpython/Lib/enum.py
Lines 790 to 794 in 712cb17
We need @ethanfurman :)
ethanfurman commentedon Sep 21, 2023
It is more accurate to say that
EnumandFlagiterate over the canonical values. For example:Aliases have always been omitted from iteration, and flag values with no, or more than one, bit(s) set are considered aliases since Python 3.11 -- this was considered a bug-fix.
gmgunter commentedon Sep 22, 2023
Oh I see. Thanks for the clarification, @ethanfurman.
Looking back over the docs now, they do pretty much convey everything that you've explained here, although some of the details are subtle. The only thing that I think isn't explicitly explained there is that zero-valued flags are considered aliases.
wimglenn commentedon Jun 27, 2024
Why isn't
F.fconsidered to be canonical?ethanfurman commentedon Jun 27, 2024
Because
fis not a flag, it is a name for the absence of flags.wimglenn commentedon Jun 27, 2024
fshows up inF.__members__, but not indir(F). Is that intended?ethanfurman commentedon Jun 28, 2024
Yes.
dir(F)doesn't list aliases, but__members__does (which also prevents aliases from being overridden -- i.e.F.f = 99raises anAttributeError).ClundXIII commentedon Dec 5, 2024
Hi,
I do have a use case where I need both alias and elements of a flag. Is there a way to explicitly iterate over either only elements and only aliases that works in both old AND new version?
Leo1690 commentedon Mar 21, 2025
@ClundXIII You can do this