Enum sera ajouté à partir de Python 3.4, qui sortira en mars de cette année. (Documentation)
Un backport a été développé qui peut être utilisé à partir de Python 2.4 et peut être installé avec pip install enum34
.
Jusqu'à présent, par exemple, les constantes ont été définies de cette manière.
class Spam:
FOO = 1
BAR = 2
BAZ = 3
Cependant, cette méthode présente les problèmes suivants.
Je l'ai résolu ad hoc et j'avais une bibliothèque, mais je veux cette bibliothèque très standard. Maintenant qu'il est dans la bibliothèque standard, utilisons-le.
Comme pour namedtuple
, si vous passez d'abord un nom de modèle, puis une liste de noms ou une chaîne séparée par des espaces, les valeurs seront attribuées dans l'ordre à partir de 1.
Le type résultant peut accéder à l'élément de trois manières: attribut, appel et indice.
>>> import enum
>>> Foo = enum.Enum("Foo", "foo bar baz")
>>> Foo.foo
<Foo.foo: 1>
>>> Foo(1)
<Foo.foo: 1>
>>> Foo["foo"]
<Foo.foo: 1>
>>> isinstance(Foo.foo, Foo)
True
L'élément a des attributs nommés et valeur.
>>> Foo.foo.value
1
>>> Foo.foo.name
'foo'
L'élément lui-même est distinct de sa valeur. Tous les éléments sont des singletons qui sont créés en même temps que la classe est créée, donc vous pouvez les comparer avec ʻisau lieu de
==`.
>>> Foo.foo == 1
False
>>> Foo.foo is Foo(1) is Foo["foo"]
True
>>> Foo.foo is Foo(1)
True
Vous pouvez également itérer.
>>> for m in Foo:
... print(m)
...
Foo.foo
Foo.bar
Foo.baz
En définissant une classe héritée au lieu d'appeler ʻEnum`, vous pouvez attribuer n'importe quelle valeur à un élément au lieu d'un numéro de série de 1.
>>> class Bar(enum.Enum):
... foo = 'x'
... bar = 'y'
... baz = 'z'
...
>>> Bar.foo
<Bar.foo: 'x'>
Dans Python 2, il n'y a (fondamentalement) aucun moyen de tirer parti de l'ordre dans lequel les éléments d'une classe sont définis. Si vous souhaitez conserver l'ordre des définitions lors de l'énumération avec l'instruction for, définissez l'attribut «order». Il s'agit d'une extension enum34 pour la prise en charge de Python 2, et le module enum Python 3.4 enregistre l'ordre des définitions sans aucune action.
>>> class Bar(enum.Enum):
... __order__ = 'foo bar baz'
... foo = 'x'
... bar = 'y'
... baz = 'z'
...
>>> list(Bar)
[<Bar.foo: 'x'>, <Bar.bar: 'y'>, <Bar.baz: 'z'>]
Parfois, il est pratique pour un élément d'agir directement comme un entier. Dans ce cas, vous pouvez utiliser IntEnum.
>>> class Foo(enum.IntEnum):
... foo = 1
... bar = 3
... baz = 5
...
>>> Foo.foo == 1
True
>>> Foo.foo + 2
3
>>> Foo.foo < Foo.bar
True
En fait, c'est la seule définition d'IntEnum.
class IntEnum(int, Enum):
"""Enum where members are also (and must be) ints"""
De cette manière, vous pouvez hériter du comportement souhaité pour l'élément.
>>> class Bar(str, enum.Enum):
... foo = 'x'
... bar = 'y'
...
>>> Bar.foo + Bar.bar
'xy'
Bien que cela soit pratique, il y a un risque que Python typé dynamiquement rend difficile de dire si une variable a un élément Enum ou un type valeur pure. Utilisons-le avec modération.
Même avec IntEnum, je ne suis pas sûr s'il existe une valeur Enum qui correspond à cette valeur entière en utilisant ʻin directement entre la valeur entière et le type Enum. ʻIn
ne peut être utilisé que sur son élément de type Enum.
>>> class Foo(enum.IntEnum):
... foo = 3
... bar = 7
...
>>> 3 in Foo
False
>>> Foo.foo in Foo
True
Vous pouvez faire n'importe quoi en héritant EnumMeta et en le personnalisant, ou en accédant directement à une API privée, mais ne vous comportez pas comme ça, appelez-le simplement normalement et vérifiez les exceptions.
Si l'appel ne trouve pas de valeur, ValueError
est renvoyé.
Vous pouvez utiliser des indices et KeyError
de la même manière lorsque vous soustrayez des éléments d'un nom.
>>> Foo(2)
ValueError: 2 is not a valid Foo
>>> Foo['xyzzy']
KeyError: 'xyzzy'
Cependant, en tant qu'API publique, un dictionnaire avec le nom comme clé et l'élément comme valeur est préparé avec le nom «members», donc lorsque vous recherchez par nom, vous pouvez également utiliser «in» ou «.get ()» ou l'opération dict habituelle. Tu peux l'utiliser.
>>> Foo.__members__
{'foo': <Foo.foo: 3>, 'bar': <Foo.bar: 7>}
>>> Foo.__members__['foo']
<Foo.foo: 3>
>>> 'xyzzy' in Foo.__members__
False
Recommended Posts