¿Cómo comparar una cadena con una enumeración de python?
enums python-3.6 (2)
Es posible que auto()
devuelva el nombre del miembro de la enumeración como su valor (que se encuentra en la sección auto
de los documentos 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 Esto requiere la versión Python 3.6 o aenum
2.0 2 ( aenum
funciona con Pythons tan antiguo como 2.7).
2 Revelación: soy el autor de Enum , el enum34
backport y la biblioteca de enumeración avanzada ( aenum
) .
Acabo de descubrir la existencia de una clase base Enum en Python y estoy tratando de imaginar cómo podría ser útil para mí.
Digamos que defino un estado de semáforo:
from enum import Enum, auto
class Signal(Enum):
red = auto()
green = auto()
orange = auto()
Digamos que recibo información de algún subsistema en mi programa, en forma de una cadena que representa un nombre de color, por ejemplo, brain_detected_colour = "red"
.
¿Cómo comparo esta cadena con las señales de mi semáforo?
Obviamente, brain_detected_colour is Signal.red
es False
, porque Signal.red
no es una cadena.
Signal(brain_detected_colour) is Signal.red
falla con ValueError: ''red'' is not a valid Signal
.
Uno no crea una instancia de un Enum . La sintaxis de Signal(foo)
se usa para acceder a los miembros de Enum por valor, que no están destinados a usarse cuando son auto()
.
Sin embargo, se puede usar una cadena para acceder a los miembros de Enum, ya que uno podría acceder a un valor en un dict
, utilizando corchetes:
Signal[brain_detected_colour] is Signal.red
Otra posibilidad sería comparar la cadena con el name
de un miembro de Enum:
# Bad practice:
brain_detected_colour is Signal.red.name
Pero aquí, no estamos probando la identidad entre los miembros de Enum, sino comparando cadenas, por lo que es una mejor práctica usar una prueba de igualdad:
# Better practice:
brain_detected_colour == Signal.red.name
(La comparación de identidad entre cadenas funcionó gracias a la internación de cadenas , en la que es mejor no confiar. Gracias a @mwchase y @Chris_Rands por informarme de ello).
Otra posibilidad más sería establecer explícitamente los valores de los miembros como sus nombres al crear el Enum:
class Signal(Enum):
red = "red"
green = "green"
orange = "orange"
(Ver esta respuesta para un método para tener este automatizado.)
Entonces, Signal(brain_detected_colour) is Signal.red
sería válido.