Python support several ways to deal with enumerations(enums):
- built in method enumerate
- class enum
- dictionary with values
Which one will be used depends on how do you want to write and access values.
Python enumerate
The method enumerate() helps working with iterators when you need to keep the iteration's count. This method will return enumerate object after adding counter to iterable.
The method starts from a given number (by default 0) and iterates over elements of iterable by adding counter and preserving the order. You can see examples about how to:
- use enumerate() method
- convert enumerate to dict
- convert enumerate to list
- changing the starting counter
The basic usage of enumerate is shown below:
for item in enumerate(['January', 'February', 'March', 'April']):
print (item)
result:
(0, 'January')
(1, 'February')
(2, 'March')
(3, 'April
Below you can find examples which cover conversion of enumerate to list or dict.
months = ['January', 'February', 'March', 'April']
enumerateMonths = enumerate(months)
# converting to dict
enumerateMonths = enumerate(months)
print(dict(enumerateMonths))
# converting to list
print(list(enumerateMonths))
enumerateMonths = enumerate(months)
print(list(enumerateMonths))
# changing the default counter
enumerateonths = enumerate(months, 10)
print(list(enumerateonths))
result:
{0: 'January', 1: 'February', 2: 'March', 3: 'April'}
[]
[(0, 'January'), (1, 'February'), (2, 'March'), (3, 'April')]
[(10, 'January'), (11, 'February'), (12, 'March'), (13, 'April')]
Note that once converted the enumerate is going to behave in different way.
Class Enum in Python
The official documentation for class Enum describe it as:
An enumeration is a set of symbolic names (members) bound to unique, constant values. Within an enumeration, the members can be compared by identity, and the enumeration itself can be iterated over.
There are several important points for Enum(enumerations):
- How to create enum in python
- How to access them
- by name
- by index
- how to iterate enumerations
- by name
- by index
- Unique enumeration values
- Comparisons
Note: Uppercase is not mandatory to be used with class enums but it's preferable. There are many good reasons to use all-uppercase names for members : code readability, PEP 8 styling, prevent undesired behaviour etc.
Create enum
Creation of Enum object is simple and can be done in two ways:
# Declaration - two ways
Sport = Enum("Sport", "BOX TENNIS KARATE RUNNING CHESS")
print(list(Sport))
class Game(Enum):
DOTA = 1
MARIO = 2
TETRIS = 3
CHESS = 4
print(list(Game))
which results in:
[<Sport.BOX: 1>, <Sport.TENNIS: 2>, <Sport.KARATE: 3>, <Sport.RUNNING: 4>, <Sport.CHESS: 5>]
[<Game.DOTA: 1>, <Game.MARIO: 2>, <Game.TETRIS: 3>, <Game.CHESS: 4>]
Access elements of enum in Python
Access of enum elements can be done in several ways as well - using dot notation and also bracket notation. Personally I prefer the second one because sometimes dot notation can lead to confusion or problems with reserved keywords:
print(Sport.BOX) # returns Sport.BOX
print(Sport["BOX"]) # returns Sport.BOX
print(Sport.BOX.name) # returns BOX
results in:
Sport.BOX
Sport.BOX
BOX
but if you try to access non existing element of enumerate you will get attribute error like:
print(Sport.box1)
product an error:
raise AttributeError(name) from None
AttributeError: box1
Access enums by indexes:
Access of enumerations by index is demonstrated below:
print(range(len(Game))) # return range(0, 4)
print(Game(1)) # return Game.dota
print(Game(1).name) # dota
result in:
range(0, 4)
Game.DOTA
DOTA
loop enumerations by index
Enum objects can be iterated by name or index. Example below show iteration by index:
for k in range(len(Game)):
a = Game(k + 1)
print(a.name, end=", ")
print()
result:
DOTA, MARIO, TETRIS, CHESS,
Iterate over enums by name
Another possible way of looping over all elements on enum is by name:
for k in Sport:
a = getattr(Sport, k.name)
print(a.name, end=", ")
result:
BOX, TENNIS, KARATE, RUNNING, CHESS,
Adding elements to enumerations in python
adding two new values to python enum with plus sign:
names = [m.name for m in Sport] + ["wrestling", "fitness"]
Sport = Enum("Sport", names)
print()
for k in Sport:
a = getattr(Sport, k.name)
print(a.name, end=", ")
result:
BOX, TENNIS, KARATE, RUNNING, CHESS, WRESTLING, FITNESS,
Test enums for a value
Very common operation in programming and enums to test if a given value is part of the enumerations this can be done by:
if Sport.box in Sport:
print("BOX is ok")
# String
if "BOXING" in Sport.__members__:
print("ok")
else:
print("BOXING is missing")
# int
games = [item.value for item in Game]
if 4 in games:
print("4 is in the Enum numbers")
result:
BOX is ok
BOXING is missing
4 is in the Enum numbers
Comparison of enums in Python
The syntax for enum comparison is by using keywords: "is" and "not":
print(Sport.BOX is Sport.BOX)
print(Sport.CHESS is Game.CHESS)
print(Sport.CHESS is not Game.CHESS)
result in:
True
False
True
Note: Enums allows duplicated values unless there is annotation - @enum.unique
which will raise error:
ValueError: duplicate values found in <enum 'Game'>: BOX -> BOXING
the same is for sharing names in enum which results in error:
TypeError: Attempted to reuse key: 'BOX'
But values can be repeated which is not good practice for me.
Note: in this article enum and enumeration are considered as names describing similar ideas/objects.
Dictionary as enumeration in Python
Sometimes dictionaries can be used as enums in python. What is best to be used depends on how is going to be used and accessed. Below you can find example of using python dict as a enum and conversion from dict to enum:
months = {'January':0, 'February':1, 'March':2}
days = dict(SUNDAY = 1, MONDAY = 2, TUESDAY = 3)
print(type(days))
m = Enum('Month', months)
d = Enum('Month', days)
print(list(m))
print(list(d))
result in:
<class 'dict'>
[<Month.January: 0>, <Month.February: 1>, <Month.March: 2>]
[<Month.SUNDAY: 1>, <Month.MONDAY: 2>, <Month.TUESDAY: 3>]
<class 'enum.EnumMeta'>