[Tutor] What would be good use cases for the enum module?
Steven D'Aprano
steve at pearwood.info
Sun Apr 9 00:13:24 EDT 2017
On Sat, Apr 08, 2017 at 10:00:21PM -0500, boB Stepp wrote:
> After reading some discussion on the Python main list about the enum
> module and some suggested changes, I thought I would read the docs on
> it at
> https://docs.python.org/3/library/enum.html?highlight=enum#module-enum
[...]
> And I am having an even harder time imagining what I would want to use
> Enum for if I don't care about the values assigned to the names and
> use auto to automatically assign values. I am having a real crisis of
> imagination here! Anyone with some commonplace and practical
> applications of the enum module?
Have you read the PEP for the enum module? There's also an earlier,
rejected PEP:
https://www.python.org/dev/peps/pep-0354/
https://www.python.org/dev/peps/pep-0435/
There are a few uses for enums where they have to behave like ints for
compatibility with code following C conventions, but basically an enum
is an abstract symbol with a pretty representation to make debugging
easier.
For example, suppose I have a function that justifies a paragraph of
text:
def justify(paragraph, where):
...
where the `where` argument specifies whether to justify the text on the
left, on the right, in the centre, or fully justified on both sides. One
way to specify that is to use numeric constants:
if where == 1:
# justify on the left
elif where == 2:
# justify on the right
elif where == 3:
# justify in the centre
elif where == 4:
# fully justify at both ends
but there's no connection between the numbers I choose and the type of
justification. I could just have sensibly used -3, 87, 4 and 32.5 as 1,
2, 3 and 4.
A bit better is to use strings:
if where == 'LEFT':
# justify on the left
elif where == 'RIGHT':
# etc
which at least now is self-documenting, but it suggests that the `where`
argument might take any string at all, which is not correct. There are
only four fixed values it can take. And besides, having to use the
quotation marks is tiresome.
So let's invent four (or even five, for Americans) named constants:
LEFT = 'LEFT'
RIGHT = 'RIGHT'
CENTRE = CENTER = 'CENTRE'
FULL = 'FULLY JUSTIFIED'
Now we're getting closer. The caller can say:
text = justify(some_text, CENTRE)
which is nice, and the justify() function can include:
if where == LEFT:
...
without quotation marks, which is also nice. That solves about 95% of
the problem.
The last niggly 5% is a subtle thing. Because the constants are strings,
we might be tempted to do string things to them, either deliberately or
by mistake:
justification_mode = CENTRE.lower() + LEFT[1:] # Oops!
# much later
justify(some_text, justification_mode)
which of course will fail, but it will fail *when the string is used*,
not when you do the string-stuff to those constants. It would be nice if
it failed straight away, at the "justification_mode" line.
To fix that, we need something which looks like a string when you print
it, for debugging, but actually isn't a string, so it doesn't accept all
the usual string methods. That's effectively just an abstract symbol,
and the way to get this in Python is with an enum.
Enums have a few other nice properties, which you may or may not care
about, but the primary use is to act as set of related named symbols.
--
Steve
More information about the Tutor
mailing list