There have been a few questions on how to implement enums in Python. Most solutions end up being more or less equivalent to something like this:
class Animal:
DOG=1
CAT=2
Others have suggest more complicated ways of constructing enums, but ultimatly the tend to look like this example when all is said and done.
Based on my experience in Java and C#, I can think of all sorts of uses for such an idiom. However, it doesn't seem to be very Pythonic. In fact, it seems that every time somebody asks why there aren't enums in Python you tend to get a bit of a groan with canned responses about how there is no reason to try and enforce compile time type safety in a language like Python, or how designs which require enums are bad smells in Python.
My question is not how to implement enums in Python, but how in general people approach solutions to problems that lend themselves to enums in a Pythonic way. In other words, how would you solve a problem which lends itself to having a data type with a discrete set of possible values without porting your Java/C# solution to Python.
Python enums are useful to represent data that represent a finite set of states such as days of the week, months of the year, etc. They were added to Python 3.4 via PEP 435. However, it is available all the way back to 2.4 via pypy. As such, you can expect them to be a staple as you explore Python programming.
Even though we can use class syntax to create Enums, Enums are not normal Python classes.
Python's enum module provides a convenient function called auto() that allows you to set automatic values for your enum members. This function's default behavior is to assign consecutive integer values to members.
It's kind of slow. We were using enums a lot in our code, until we noticed that enum overhead takes up single digit percentages of our CPU time! Luckily, it only took a few hours to write a much faster implementation with almost the same functionality.
PEP 435 was just accepted, which adds the enum package to the standard library along with the Enum class and other derivatives like the IntEnum. This means that starting with Python 3.4, the "pythonic" way to use enums in a design is with this package. It will look something like this:
>>> from enum import Enum
>>> class Color(Enum):
... red = 1
... green = 2
... blue = 3
>>> print(Color.red)
Color.red
>>> print(Color.red.name)
red
>>>> for color in Color:
.... print(color)
Color.red
Color.green
Color.blue
The key feature of this design is that keys can reject comparison where it doesn't make sense (unlike the string keys suggested in other answers), allow keys to have pretty printing unrelated to the key value, as well as giving the key values special properties by defining methods on the Enum subclass, in addition to the property of throwing an explicit and understandable error should the user try to use an illegal key from the Enum class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With