codebreaker
codebreaker

Reputation: 813

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?

Upvotes: 1

Views: 641

Answers (2)

Ethan Furman
Ethan Furman

Reputation: 69288

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.

Upvotes: 4

Quintium
Quintium

Reputation: 368

You could just create a list basic_directions = [NORTH, EAST, SOUTH, WEST] and use the same for loop that you wrote before:

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

Upvotes: 1

Related Questions