python enums python-3.6

¿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.