Псевдонимы перечислений в Python и @enum.unique
В этом руководстве вы узнаете о псевдонимах элементов перечисления в Python и о том, как использовать декоратор enum unique для обеспечения уникальности значений элементов.
- Что такое псевдонимы элементов перечислений?
- Когда использовать псевдонимы перечислений
- Декоратор @enum.unique
Что такое псевдонимы элементов перечислений?
По определению значения членов перечисления уникальны. Однако вы можете создавать разные имена элементов с одинаковыми значениями.
Например, следующий код определяет перечисление Color:
from enum import Enum class Color(Enum): RED = 1 CRIMSON = 1 SALMON = 1 GREEN = 2 BLUE = 3
В этом примере перечисление Color содержит элементы RED, CRIMSON и SALMON с одинаковым значением 1. Когда вы определяете несколько членов перечисления с одинаковыми значениями, Python создает не разные члены, а псевдонимы. RED является основным элементом, а CRIMSON и SALMON являются псевдонимами члена RED.
Следующие операторы возвращают значение True, поскольку CRIMSON и SALMON являются членами RED:
print(Color.RED is Color.CRIMSON) print(Color.RED is Color.SALMON)
Выход:
True True
Когда вы ищете элемент по значению, вы всегда получаете основной элемент, а не псевдонимы. Например, следующий оператор возвращает элемент RED:
print(Color(1))
Выход:
Color.RED
При переборе перечисления с псевдонимами вы получите только основные члены, а не псевдонимы. Пример:
for color in Color: print(color)
Он возвращает только три члена:
Color.RED Color.GREEN Color.BLUE
Чтобы получить все члены, включая псевдонимы, вам нужно использовать свойство __member__ класса перечисления. Например:
from enum import Enum from pprint import pprint class Color(Enum): RED = 1 CRIMSON = 1 SALMON = 1 GREEN = 2 BLUE = 3 pprint(Color.__members__)
Выход:
mappingproxy({'BLUE': <Color.BLUE: 3>, 'CRIMSON': <Color.RED: 1>, 'GREEN': <Color.GREEN: 2>, 'RED': <Color.RED: 1>, 'SALMON': <Color.RED: 1>})
Как ясно видно из выходных данных, CRIMSON и SALMON ссылаются на один и тот же объект, на который ссылается член RED:
<Color.RED: 1>
Когда использовать псевдонимы перечислений
Псевдонимы перечисления могут быть полезны в некоторых ситуациях. Например, предположим, что вам приходится иметь дело с API двух разных систем. Каждая система имеет свой статус ответа, имеющий то же значение, что показано в следующей таблице:
Система 1 | Система 2 | Значение |
---|---|---|
REQUESTING | PENDING | Запрос находится в обработке |
OK | FULFILLED | Запрос успешно выполнен |
NOT_OK | REJECTED | Запрос не выполнен |
Чтобы стандартизировать коды состояния этих систем, вы можете использовать псевдонимы перечисления следующим образом:
Ваша система | Система 1 | Система 2 | Значение |
---|---|---|---|
IN_PROGRESS | REQUESTING | PENDING | Запрос находится в обработке |
SUCCESS | OK | FULFILLED | Запрос успешно выполнен |
ERROR | NOT_OK | REJECTED | Запрос не выполнен |
Следующий код определяет перечисление ResponseStatus с псевдонимами:
from enum import Enum class ResponseStatus(Enum): # in progress IN_PROGRESS = 1 REQUESTING = 1 PENDING = 1 # success SUCCESS = 2 OK = 2 FULFILLED = 2 # error ERROR = 3 NOT_OK = 3 REJECTED = 3
Ниже сравнивается код ответа системы 1, чтобы проверить, был ли запрос успешным или нет:
code = 'OK' if ResponseStatus[code] is ResponseStatus.SUCCESS: print('The request completed successfully')
Выход:
The request completed successfully
Аналогичным образом вы можете проверить код ответа от системы 2, чтобы убедиться, что запрос был успешным:
code = 'FULFILLED' if ResponseStatus[code] is ResponseStatus.SUCCESS: print('The request completed successfully')
Выход:
print('The request completed successfully')
Декоратор @enum.unique
Чтобы определить перечисление без псевдонимов, вы можете осторожно использовать уникальные значения для его членов. Например:
from enum import Enum class Day(Enum): MON = 'Monday' TUE = 'Tuesday' WED = 'Wednesday' THU = 'Thursday' FRI = 'Friday' SAT = 'Saturday' SUN = 'Sunday'
Но вы можете случайно использовать одни и те же значения для двух членов, например:
class Day(Enum): MON = 'Monday' TUE = 'Monday' WED = 'Wednesday' THU = 'Thursday' FRI = 'Friday' SAT = 'Saturday' SUN = 'Sunday'
В этом примере TUE является псевдонимом члена MON, чего вы, возможно, не ожидаете. Чтобы гарантировать, что перечисление не имеет псевдонима, вы можете использовать декоратор @enum.unique из модуля enum.
Когда вы используете декоратор @enum.unique, Python выдает исключение, если перечисление имеет псевдонимы.
Например, следующее вызовет ValueError:
import enum from enum import Enum @enum.unique class Day(Enum): MON = 'Monday' TUE = 'Monday' WED = 'Wednesday' THU = 'Thursday' FRI = 'Friday' SAT = 'Saturday' SUN = 'Sunday'
Ошибка:
ValueError: duplicate values found in <enum 'Day'>: TUE -> MON