pythonenumsenum-flagsbitflags

Can I decompose a Python Flag enum into its fundamental parts?


I have an enum that represents the directions you're allowed to move for a given cell in a maze:

class Direction(Flag):
    NORTH = 1
    EAST = 2
    SOUTH = 4
    WEST = 8
    NE = NORTH | EAST
    NW = NORTH | WEST
    ...etc
    NESW = NORTH | EAST | SOUTH | WEST

This makes it easy to check if you can go west, you can just check cell.directions & Direction.WEST. But what if I want to iterate over the possible directions? Something like for d in cell.directions: ..., but you can't do this. If I didn't alias every possible combination of directions (which makes things easier in my code), then I could do:

for d in Direction:
    if cell.directions & d:
        ....

But this won't work for me because it would iterate over all the combined directions too, rather than just the four basic cardinal directions. Is there a good solution here?


Solution

  • In Python 3.11 this works as you would expect: iteration only provides the canonical (i.e. powers of two) flags, all others are considered aliases.

    Even in prior versions, though, this works:

    from enum import Flag
    
    class Direction(Flag):
        NORTH = 1
        EAST = 2
        SOUTH = 4
        WEST = 8
    
    NORTH, EAST, SOUTH, WEST = Direction
    
    directions = NORTH | EAST
    d = NORTH
    if d in directions:
        print('going North!')
    

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