3

I'm working with enum lately and I dont really get the utility of them in some cases. I hope my question is not too trivial or too stupid, and I would really love to better understand the logic behind this python structure. One common use I found online or in some pieces of code I have been working on lately is the use of values that are strings like for example:

from enum import Enum

class Days(Enum):
    MONDAY = 'monday'
    TUESDAY = 'tuesday'
    ...
    SUNDAY = 'sunday'

And here from my humble prospective, the values seems redundant: if I print the values of some member I obtain the following:

print(Days.MONDAY.value)
>> 'monday'

I totally understand the utility when the values are numbers and they represent a gerarchic structure like for example

class Levels(Enum):
    HIGH = 10
    MID = 5
    LOW = 0

In which you can do stuff like:

HIGH > LOW
> True

But in a lot of example and actual code use, I see the first approach, the one with MONDAY = 'monday', i.e. when the values are string instead of numerical values, and this case I really dont understand the utility of having a key that is pretty much equal to the value.

If anyone can help me understand, or show some utilities I would really love to understand new stuff.

1
  • 1
    For one thing, just because the enum name happens to currently match its value, that doesn't mean that must always be the case. You could come in later and refactor the Days enum to instead use MON, TUE, WED, etc, without breaking any code that relies on the string values. Commented Jul 11, 2022 at 13:28

3 Answers 3

5

The members (should) always be named in all uppercase (per the very first note on the enum docs), so if you want them to have "names" that are in some other casing, you can assign strings with arbitrary case, which may be more human-friendly when it comes time to display the values to the user.

You can also convert from said values to the enum constant easily, with the Enum's constructor, e.g.:

Days('monday') is Days.MONDAY  # This is True

so if the data from the user (or database or whatever) has specific values, you can easily convert them to their logical Enum equivalents this way.

If the values really aren't meaningful, you can just assign auto() to all of them and not think about the values.

Just in case you're asking "why not use the strings themselves?", the general advantage to enums is guaranteed uniqueness and exhaustiveness for efficient checks and self-documenting code. If you use the strings directly, you have to use == checks (str has no guarantee that equal values are the same object unless you explicitly intern them, so is checks can't be used), and people can pass in strings that don't actually come from the expected set of strings. With Enums there is a central definition of all possible values (and therefore all other values are not possible), and since the values are all guaranteed singletons, when you have a member of that Enum, you can use is/is not testing for cheap identity testing (in CPython at least, it's literally just a pointer comparison) without relying on value equality tests, ==/!=, that invoke the more expensive rich comparison machinery. This even works when you make aliases for the same enum member, e.g.:

class Foo(Enum):
    SPAM = 1
    EGGS = 2
    ALSO_SPAM = 1

which seamlessly makes Foo.ALSO_SPAM the same object as Foo.SPAM so Foo.SPAM is Foo.ALSO_SPAM is true, allowing two aliases with different names to be used interchangably.

Sign up to request clarification or add additional context in comments.

1 Comment

Yes that is exactly the answer I was looking for, in particular the "why not use the strings themselves?" part. Thank you very much!
2

In addition to @ShadowRanger's answer: The primary reason why Enum has both a name and a value field is so meaningful constants can have easy to use names -- constants such as database values, various codes (http, error, response, etc.) -- in other words, so Enum can provide an easy interface with other systems.

Comments

1

It's one approach to adding type safety to your code. Even if Days looks like a collection of strings, it's not a subclass/subtype/special-case of str.

>>> isinstance(Days.MONDAY, Days)
True
>>> isinstance('monday', Days)
False
>>> isinstance(Days.MONDAY, str)
False

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.