Как сравнить строку с перечислением python?
Я только что обнаружил существование Enum базового класса в python, и я пытаюсь представить, как это может быть полезно мне.
Скажем, я определяю статус светофора:
from enum import Enum, auto
class Signal(Enum):
red = auto()
green = auto()
orange = auto()
Скажем, я получаю информацию от некоторой подсистемы в своей программе в виде строки, представляющей название цвета, например brain_detected_colour = "red"
.
Как сравнить эту строку с сигналами светофора?
Очевидно, brain_detected_colour is Signal.red
является False
, потому что Signal.red
не является строкой.
Signal(brain_detected_colour) is Signal.red
не работает с ValueError: 'red' is not a valid Signal
.
Ответы
Ответ 1
Не создается экземпляр Enum.
Синтаксис Signal(foo)
используется для доступа к членам Enum по значению, которые не предназначены для использования, когда они auto()
.
Однако можно использовать строку в доступ к элементам Enum, чтобы получить доступ к значению в dict
, используя квадратные скобки:
Signal[brain_detected_colour] is Signal.red
Другая возможность - сравнить строку с name
члена Enum:
# Bad practice:
brain_detected_colour is Signal.red.name
Но здесь мы не проверяем идентификацию между членами Enum, а сравниваем строки, поэтому лучше использовать тест равенства:
# Better practice:
brain_detected_colour == Signal.red.name
(Сравнение идентичности строк, выполненных благодаря string interning, на что лучше не полагаться. Спасибо @mwchase и @Chris_Rands за чтобы я знал об этом.)
Еще одна возможность заключалась бы в том, чтобы явным образом задавать значения членов как их имена при создании Enum:
class Signal(Enum):
red = "red"
green = "green"
orange = "orange"
(см. этот ответ для метода, который должен быть автоматизирован.)
Тогда Signal(brain_detected_colour) is Signal.red
будет действительным.
Ответ 2
Возможно, что auto()
возвращает имя члена перечисления как его значение (которое находится в разделе auto
в документах 1
>>> class AutoName(Enum):
... def _generate_next_value_(name, start, count, last_values):
... return name
...
>>> class Ordinal(AutoName):
... NORTH = auto()
... SOUTH = auto()
... EAST = auto()
... WEST = auto()
...
>>> list(Ordinal)
[<Ordinal.NORTH: 'NORTH'>, <Ordinal.SOUTH: 'SOUTH'>, <Ordinal.EAST: 'EAST'>, <Ordinal.WEST: 'WEST'>]
1 Для этого требуется версия Python 3.6, или aenum
2.0 2 (aenum
работает с Pythons как старое как 2.7).
2 Раскрытие информации: Я являюсь автором Python stdlib Enum
, enum34
backport, а Расширенное перечисление (aenum
) библиотека.