Je viens de découvrir l'existence d'une classe de base Enum dans python et j'essaie d'imaginer comment cela pourrait m'être utile.
Disons que je définis un statut de feu de circulation:
from enum import Enum, auto
class Signal(Enum):
red = auto()
green = auto()
orange = auto()
Disons que je reçois des informations d'un sous-système de mon programme, sous la forme d'une chaîne représentant un nom de couleur, par exemple brain_detected_colour = "red"
.
Comment comparer cette chaîne à mes feux de signalisation?
Évidemment, brain_detected_colour is Signal.red
Est False
, car Signal.red
N'est pas une chaîne.
Signal(brain_detected_colour) is Signal.red
échoue avec ValueError: 'red' is not a valid Signal
.
On ne crée pas un instance d'un Enum . La syntaxe Signal(foo)
est utilisée pour accéder aux membres Enum par valeur, qui ne sont pas destinés à être utilisés lorsqu'ils sont auto()
.
Cependant, on peut utiliser une chaîne pour accéder aux membres Enum comme on accéderait à une valeur dans un dict
, en utilisant des crochets:
Signal[brain_detected_colour] is Signal.red
Une autre possibilité serait de comparer la chaîne au name
d'un membre Enum:
# Bad practice:
brain_detected_colour is Signal.red.name
Mais ici, nous ne testons pas l'identité entre les membres Enum, mais comparons les chaînes, il est donc préférable d'utiliser un test d'égalité:
# Better practice:
brain_detected_colour == Signal.red.name
(La comparaison d'identité entre les chaînes a fonctionné grâce à internement des chaînes , ce qui vaut mieux ne pas être invoqué. Merci @mwchase et @Chris_Rands de m'avoir informé de cela.)
Une autre possibilité serait de définir explicitement les valeurs des membres comme leurs noms lors de la création de l'énumération:
class Signal(Enum):
red = "red"
green = "green"
orange = "orange"
(Voir cette réponse pour une méthode pour automatiser cela.)
Ensuite, Signal(brain_detected_colour) is Signal.red
serait valide.
Il est possible que auto()
renvoie le nom du membre enum comme valeur (qui se trouve dans la section auto
des documents1:
>>> 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 Cela nécessite la version Python 3.6 ou aenum
2.02 (aenum
fonctionne avec des Pythons aussi anciens que 2.7).
2 Divulgation: je suis l'auteur du Python stdlib Enum
, le enum34
backport , et la bibliothèque Advanced Enumeration (aenum
) .