Автор оригинала: Doug Hellmann.
Модуль ENUM
определяет тип перечисления с итерацией и возможностями сравнения. Его можно использовать для создания четко определенных символов для значений, а не используя литеральные целые числа или строки.
Создание перечислений
Новое перечисление определяется с помощью синтаксиса Code> Code с помощью подкласса Enum
и добавление атрибутов классов, описывающих значения.
enum_create.py
import enum class BugStatus(enum.Enum): new 7 incomplete 6 invalid 5 wont_fix 4 in_progress 3 fix_committed 2 fix_released 1 print('\nMember name: {}'.format(BugStatus.wont_fix.name)) print('Member value: {}'.format(BugStatus.wont_fix.value))
Члены ENUM
преобразуются в экземпляры, так как класс анализируется. Каждый экземпляр имеет имя <код> свойство, соответствующее имени участника и значение , соответствующее значению, назначенному имени в определении класса.
$ python3 enum_create.py Member name: wont_fix Member value: 4
Итерация
Итализация по поводу Enum класса производит отдельные члены перечисления.
enum_iterate.py
import enum class BugStatus(enum.Enum): new 7 incomplete 6 invalid 5 wont_fix 4 in_progress 3 fix_committed 2 fix_released 1 for status in BugStatus: print('{:15} = {}'.format(status.name, status.value))
Участники производятся в том порядке, в котором они объявлены в определении класса. Имена и значения не используются для их сортировки.
$ python3 enum_iterate.py new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1
Сравнение enums.
Потому что члены перечисления не упорядочены, они поддерживают только сравнение личности и равенством.
enum_comparison.py
import enum class BugStatus(enum.Enum): new 7 incomplete 6 invalid 5 wont_fix 4 in_progress 3 fix_committed 2 fix_released 1 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))
Операторы большего и менее чем сравнение повышают <код> ImporeError исключения.
$ python3 enum_comparison.py Equality: False True Identity: False True Ordered by value: Cannot sort: '<' not supported between instances of 'BugStatus ' and 'BugStatus'
Используйте класс INTENUM
для перечислений, в которых члены должны вести себя больше похожи на цифры, например, для поддержки сравнений.
enum_intenum.py
import enum class BugStatus(enum.IntEnum): new 7 incomplete 6 invalid 5 wont_fix 4 in_progress 3 fix_committed 2 fix_released 1 print('Ordered by value:') print('\n'.join(' ' + s.name for s in sorted(BugStatus)))
$ python3 enum_intenum.py Ordered by value: fix_released fix_committed in_progress wont_fix invalid incomplete new
Уникальные значения перечисления
Участники Enum с одинаковым значением отслеживаются как ссылки на псевдоним к тому же объекту-члену. Псевдонимы не вызывают повторных значений в итераторе для ENUM
.
enum_aliases.py
import enum class BugStatus(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 BugStatus: print('{:15} = {}'.format(status.name, status.value)) print('\nSame: by_design is wont_fix: ', BugStatus.by_design is BugStatus.wont_fix) print('Same: closed is fix_released: ', BugStatus.closed is BugStatus.fix_released)
Поскольку <код> by_design и <код> закрыты – псевдонимы для других участников, они не отображаются отдельно на выходе при итерации по адресу <код> enum . Каноническое имя для члена – это имя, прикрепленное к значению.
$ python3 enum_aliases.py new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1 Same: by_design is wont_fix: True Same: closed is fix_released: True
Чтобы все участники имели уникальные значения, добавьте <код> @Unique декоратор на <код> enum .
enum_unique_enforce.py
import enum @enum.unique class BugStatus(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
Участники с повторяющимися значениями вызывают ValueError , когда <код> enum интерпретируется.
$ python3 enum_unique_enforce.py Traceback (most recent call last): File "enum_unique_enforce.py", line 11, inclass BugStatus(enum.Enum): File ".../lib/python3.7/enum.py", line 848, in unique (enumeration, alias_details)) ValueError: duplicate values found in : by_design -> wont_fix, closed -> fix_released
Создание перечисления программно
В некоторых случаях удобнее создавать перечисление программно, а не жестко кодирующим их в определении класса. Для этих ситуаций Enum
также поддерживает передачу имен элементов и значений классу конструктора.
enum_programmatic_create.py
import enum 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))
Объект
– это имя перечисления, которое используется для создания представления членов. Имена Argument перечислены члены перечисления. Когда пропущена одна строка, она разделена на пробел и запятые, и полученные токены используются в качестве имени для членов, которые автоматически назначаются значения, начиная с 1
.
$ python3 enum_programmatic_create.py Member: BugStatus.new All members: fix_released = 1 fix_committed = 2 in_progress = 3 wont_fix = 4 invalid = 5 incomplete = 6 new = 7
Для более контроля над значениями, связанными с элементами, может быть заменена последовательностью двухфункциональных кортежей или имена сопоставления словаря к значениям.
enum_programmatic_mapping.py
import enum 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))
В этом примере список кортежей из двух частей приведен вместо одной строки, содержащей только имена элементов. Это позволяет восстановить реконструкцию BUGSTATUS
перечисления с членами в том же порядке, что и версия, определенная в Enum_Crate.py
.
$ python3 enum_programmatic_mapping.py All members: new = 7 incomplete = 6 invalid = 5 wont_fix = 4 in_progress = 3 fix_committed = 2 fix_released = 1
Значения не целочисленных членов
Значения элементов элементов не ограничены целыми числами. На самом деле любой тип объекта может быть связан с участником. Если значение представляет собой кортеж, члены передаются как отдельные аргументы <код> __ init __ () .
enum_tuple_values.py
import enum 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))
В этом примере каждое значение элемента представляет собой кортеж, содержащий числовой идентификатор (например, может храниться в базе данных), так и в списке действительных переходов от текущего состояния.
$ python3 enum_tuple_values.py Name: BugStatus.in_progress Value: (3, ['new', 'fix_committed']) Custom attribute: ['new', 'fix_committed'] Using attribute: True
Для более сложных случаев кортежи могут стать громоздкими. Поскольку значения элементов могут быть любым типом объекта, словари могут использоваться для случаев, когда есть много отдельных атрибутов для отслеживания для каждого значения Enum. Комплексные значения передаются непосредственно к <код> __ init __ () как единственный аргумент, отличный от <код> Self .
enum_complex_values.py
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))
В этом примере выражается те же данные, что и предыдущий пример, используя словари, скорее
$ python3 enum_complex_values.py Name: BugStatus.in_progress Value: {'num': 3, 'transitions': ['new', 'fix_committed']} Custom attribute: ['new', 'fix_committed'] Using attribute: True
Смотрите также
- Стандартная библиотечная документация для Enum
- Pep 435 – добавление типа enum в стандартную библиотеку Python
- flufl.enum – оригинальное вдохновение для <код> enum , by barry warsaw.