A new enumeration is defined using the class syntax by subclassing Enum and adding class attributes describing the values
In [ ]:
import enum
In [ ]:
class BugStatus(enum.Enum):
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1
In [ ]:
print("member name: {}".format(BugStatus.wont_fix.name))
print("member value: {}".format(BugStatus.wont_fix.value))
In [ ]:
BugStatus(7)
In [ ]:
# if you want access enum members by name, use item access
In [ ]:
BugStatus['']
Iterating over the enum class pruduces the indivisual members of the member
In [ ]:
for status in BugStatus:
print("{}:{}".format(status.name, status.value))
Note: The members are produced in the order they are declared in the class definition. The names and values are not used to sort them.
Because enumeration members are not ordered. They only support equality and identify test
In [ ]:
actual_state = BugStatus.wont_fix
desired_state = BugStatus.fix_released
print('Equality:',
actual_state == desired_state,
actual_state == BugStatus.wont_fix)
print('Identity:',
actual_state is desired_state,
actual_state is BugStatus.wont_fix)
print('Ordered by value:')
try:
print('\n'.join(' ' + s.name for s in sorted(BugStatus)))
except TypeError as err:
print(' Cannot sort: {}'.format(err))
In [ ]:
class BugStatusInt(enum.IntEnum):
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1
In [ ]:
actual_state = BugStatusInt.wont_fix
desired_state = BugStatusInt.fix_released
print('Equality:',
actual_state == desired_state,
actual_state == BugStatusInt.wont_fix)
print('Identity:',
actual_state is desired_state,
actual_state is BugStatusInt.wont_fix)
print("comparison: ")
print("new is bigger then invalid:", BugStatusInt.new > BugStatusInt.invalid)
print('Ordered by value:')
print('\n'.join(' ' + s.name for s in sorted(BugStatusInt)))
Enum members with the same value are tracked as alias references to the same member object. Aliases do not cause repeated values to be present in the iterator for the Enum
In [ ]:
class BugStatusUnique(enum.Enum):
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1
by_design = 4
closed = 1
for status in BugStatusUnique:
print('{:15} = {}'.format(status.name, status.value))
print('\nSame: by_design is wont_fix: ',
BugStatusUnique.by_design is BugStatusUnique.wont_fix)
print('Same: closed is fix_released: ',
BugStatusUnique.closed is BugStatusUnique.fix_released)
To require all members to have unique values, add the decorator
In [ ]:
@enum.unique
class BugStatusUniqueDecorator(enum.Enum):
new = 7
incomplete = 6
invalid = 5
wont_fix = 4
in_progress = 3
fix_committed = 2
fix_released = 1
# This will trigger an error with unique applied.
by_design = 4
closed = 1
Members with repeated values trigger a ValueError
exception when the Enum
class being interpreted
In [ ]:
BugStatus = enum.Enum(
value='BugStatus',
names=('fix_released fix_committed in_progress '
'wont_fix invalid incomplete new'),
)
print('Member: {}'.format(BugStatus.new))
print('\nAll members:')
for status in BugStatus:
print('{:15} = {}'.format(status.name, status.value))
value: the name of the enumration names: lists the member of the enumeration, if a string is passed. it is split on the whitespace and commas. the value to names is starting with 1
If you want control the value associated with members, the names string can be replaced with a sequence of 2 part tuples or a dictionary mapping names to values
In [ ]:
BugStatus = enum.Enum(
value='BugStatus',
names=[
('new', 7),
('incomplete', 6),
('invalid', 5),
('wont_fix', 4),
('in_progress', 3),
('fix_committed', 2),
('fix_released', 1),
],
)
print('All members:')
for status in BugStatus:
print('{:15} = {}'.format(status.name, status.value))
Enum member values are not restricted to integers. In fact, any type of object can be associated with a member. If the value is a tuple, the members are passed as individual arguments to init().
In [ ]:
class BugStatus(enum.Enum):
new = (7, ['incomplete',
'invalid',
'wont_fix',
'in_progress'])
incomplete = (6, ['new', 'wont_fix'])
invalid = (5, ['new'])
wont_fix = (4, ['new'])
in_progress = (3, ['new', 'fix_committed'])
fix_committed = (2, ['in_progress', 'fix_released'])
fix_released = (1, ['new'])
def __init__(self, num, transitions):
self.num = num
self.transitions = transitions
def can_transition(self, new_state):
return new_state.name in self.transitions
print('Name:', BugStatus.in_progress)
print('Value:', BugStatus.in_progress.value)
print('Custom attribute:', BugStatus.in_progress.transitions)
print('Using attribute:',
BugStatus.in_progress.can_transition(BugStatus.new))
In [ ]:
BugStatus.new.transitions
For more complex cases, tuples might become unwieldy. Since member values can be any type of object, dictionaries can be used for cases where there are a lot of separate attributes to track for each enum value. Complex values are passed directly to init() as the only argument other than self.
In [ ]:
import enum
class BugStatus(enum.Enum):
new = {
'num': 7,
'transitions': [
'incomplete',
'invalid',
'wont_fix',
'in_progress',
],
}
incomplete = {
'num': 6,
'transitions': ['new', 'wont_fix'],
}
invalid = {
'num': 5,
'transitions': ['new'],
}
wont_fix = {
'num': 4,
'transitions': ['new'],
}
in_progress = {
'num': 3,
'transitions': ['new', 'fix_committed'],
}
fix_committed = {
'num': 2,
'transitions': ['in_progress', 'fix_released'],
}
fix_released = {
'num': 1,
'transitions': ['new'],
}
def __init__(self, vals):
self.num = vals['num']
self.transitions = vals['transitions']
def can_transition(self, new_state):
return new_state.name in self.transitions
print('Name:', BugStatus.in_progress)
print('Value:', BugStatus.in_progress.value)
print('Custom attribute:', BugStatus.in_progress.transitions)
print('Using attribute:',
BugStatus.in_progress.can_transition(BugStatus.new))
In [ ]: