How can I implement an enumeration type (spelled enum
in some languages) in Python? What is the common practice to get this functionality?
Asked
Active
Viewed 1.4e+01k times
153

Karl Knechtel
- 62,466
- 11
- 102
- 153

Joan Venge
- 315,713
- 212
- 479
- 689
-
18Now there is a standard Enum type in Python 3.4. Read this post: http://stackoverflow.com/questions/16653129/future-compatible-enums-in-2-7 – Javier Apr 01 '14 at 15:17
-
4Here is the PEP for the enum type that is now in Python: https://www.python.org/dev/peps/pep-0435/ – shuttle87 Jul 27 '15 at 02:22
4 Answers
375
class Materials:
Shaded, Shiny, Transparent, Matte = range(4)
>>> print Materials.Matte
3
Update: For Python 3.4+:
As of Python 3.4+, you can now use Enum
(or IntEnum
for enums with int
values) from the enum module. Use enum.auto
to increment the values up automatically:
import enum
class Materials(enum.IntEnum):
Shaded = 1
Shiny = enum.auto()
Transparent = 3
Matte = enum.auto()
print(Materials.Shiny == 2) # True
print(Materials.Matte == 4) # True
-
17
-
The only problem is I need the first item to be 1. Is that possible to do with your method? – Joan Venge Mar 31 '09 at 21:41
-
Of all the methods i've seen, this is probably my favorite. Very elegant! – goldenratio Mar 31 '09 at 22:31
-
4@Joan You could do `_unused, Shaded, Shiny, Transparent, Matte = range(5)` – zekel Dec 09 '10 at 02:12
-
83Kinda late, but you can also do `Shaded, Shiny, Transparent, Matte = range(1, 5)` if you don't like having the `_unused` there – Davy8 Jan 30 '11 at 17:42
-
3You also don't have to use range, assigning each class variable a value individually. – bret Jun 13 '12 at 22:38
-
4Unfortunately, this method of making an enum is incomplete, as the enums cannot be iterated over, nor is each value an unique type (e.g. just an int). – Gewthen Jun 10 '15 at 01:43
-
@Gewthen In many languages, enums are "just an int". Isn't that more or less expected? If necessary, you could implement an appropriate [iterator](http://stackoverflow.com/a/231855/1796585). – Mads Y Sep 02 '15 at 18:52
-
@MadsY In other languages they are simply syntactic sugar, whereas in other languages (e.g. Python3) they are not. Having a strong type for your values is generally better in strongly types languages, because it utilizes the language more. If they are only just numbers it's more to remember when debugging or looking at logs. I'd rather just see `Materials.shinny` in a log than `1` because `1` tells me much less than `Materials.shinny` – Gewthen Oct 17 '15 at 05:26
-
9
21
I've seen this pattern several times:
>>> class Enumeration(object):
def __init__(self, names): # or *names, with no .split()
for number, name in enumerate(names.split()):
setattr(self, name, number)
>>> foo = Enumeration("bar baz quux")
>>> foo.quux
2
You can also just use class members, though you'll have to supply your own numbering:
>>> class Foo(object):
bar = 0
baz = 1
quux = 2
>>> Foo.quux
2
If you're looking for something more robust (sparse values, enum-specific exception, etc.), try this recipe.

ninjagecko
- 88,546
- 24
- 137
- 145

Ben Blank
- 54,908
- 28
- 127
- 156
9
I have no idea why Enums are not support natively by Python. The best way I've found to emulate them is by overridding _ str _ and _ eq _ so you can compare them and when you use print() you get the string instead of the numerical value.
class enumSeason():
Spring = 0
Summer = 1
Fall = 2
Winter = 3
def __init__(self, Type):
self.value = Type
def __str__(self):
if self.value == enumSeason.Spring:
return 'Spring'
if self.value == enumSeason.Summer:
return 'Summer'
if self.value == enumSeason.Fall:
return 'Fall'
if self.value == enumSeason.Winter:
return 'Winter'
def __eq__(self,y):
return self.value==y.value
Usage:
>>> s = enumSeason(enumSeason.Spring)
>>> print(s)
Spring

Spell
- 384
- 4
- 11
-
4PEP354 has a rejection notice. See http://www.python.org/dev/peps/pep-0354/#rejection-notice – Fred Larson Mar 31 '09 at 20:33
-
4It would be quicker to have a class dictionary {"Spring": 0, "Summer":1, ...} and use __init__ to iterate through entries and set attributes, because then __str__ could just look the value up rather than being coded by hand for every case. – Charles J. Daniels Mar 29 '15 at 08:51
-
2
6
You could probably use an inheritance structure although the more I played with this the dirtier I felt.
class AnimalEnum:
@classmethod
def verify(cls, other):
return issubclass(other.__class__, cls)
class Dog(AnimalEnum):
pass
def do_something(thing_that_should_be_an_enum):
if not AnimalEnum.verify(thing_that_should_be_an_enum):
raise OhGodWhy

Trey Stout
- 6,231
- 3
- 24
- 27