Ich bin hauptsächlich ein C#-Entwickler, aber ich arbeite derzeit an einem Projekt in Python.
Wie kann ich das Äquivalent einer Enum in Python darstellen?
Ich bin hauptsächlich ein C#-Entwickler, aber ich arbeite derzeit an einem Projekt in Python.
Wie kann ich das Äquivalent einer Enum in Python darstellen?
Enums wurden zu Python 3.4 hinzugefügt, wie in PEP 435 . Es wurde auch schon zurückportiert nach 3.3, 3.2, 3.1, 2.7, 2.6, 2.5 und 2.4 auf pypi.
Für fortgeschrittene Enum-Techniken versuchen Sie die Aenum-Bibliothek (2.7, 3.3+, gleicher Autor wie enum34
. Der Code ist nicht perfekt kompatibel zwischen py2 und py3, z.B. benötigen Sie __order__
in Python 2 ).
enum34
tun $ pip install enum34
aenum
tun $ pip install aenum
Installation von enum
(ohne Zahlen) wird eine völlig andere und inkompatible Version installiert.
from enum import Enum # for enum34, or the stdlib version
# from aenum import Enum # for the aenum version
Animal = Enum('Animal', 'ant bee cat dog')
Animal.ant # returns <Animal.ant: 1>
Animal['ant'] # returns <Animal.ant: 1> (string lookup)
Animal.ant.name # returns 'ant' (inverse lookup)
oder gleichwertig:
class Animal(Enum):
ant = 1
bee = 2
cat = 3
dog = 4
In früheren Versionen war eine Möglichkeit, Enums zu erreichen:
def enum(**enums):
return type('Enum', (), enums)
die wie folgt verwendet wird:
>>> Numbers = enum(ONE=1, TWO=2, THREE='three')
>>> Numbers.ONE
1
>>> Numbers.TWO
2
>>> Numbers.THREE
'three'
Sie können die automatische Aufzählung auch leicht mit etwas wie diesem unterstützen:
def enum(*sequential, **named):
enums = dict(zip(sequential, range(len(sequential))), **named)
return type('Enum', (), enums)
und wie folgt verwendet:
>>> Numbers = enum('ZERO', 'ONE', 'TWO')
>>> Numbers.ZERO
0
>>> Numbers.ONE
1
Auf diese Weise kann eine Unterstützung für die Rückkonvertierung der Werte in Namen hinzugefügt werden:
def enum(*sequential, **named):
enums = dict(zip(sequential, range(len(sequential))), **named)
reverse = dict((value, key) for key, value in enums.iteritems())
enums['reverse_mapping'] = reverse
return type('Enum', (), enums)
Dies überschreibt alles, was diesen Namen trägt, ist aber nützlich, um Ihre Enums in der Ausgabe darzustellen. Es wird ein KeyError
wenn die umgekehrte Zuordnung nicht existiert. Mit dem ersten Beispiel:
>>> Numbers.reverse_mapping['three']
'THREE'
Wenn Sie MyPy verwenden, ist eine weitere Möglichkeit, "enums" auszudrücken, mit typing.Literal
.
Zum Beispiel:
from typing import Literal #python >=3.8
from typing_extensions import Literal #python 2.7, 3.4-3.7
Animal = Literal['ant', 'bee', 'cat', 'dog']
def hello_animal(animal: Animal):
print(f"hello {animal}")
hello_animal('rock') # error
hello_animal('bee') # passes
Vor PEP 435 gab es in Python kein Äquivalent, aber man konnte sein eigenes implementieren.
Ich selbst halte es gerne einfach (ich habe einige schrecklich komplexe Beispiele im Netz gesehen), etwa so ...
class Animal:
DOG = 1
CAT = 2
x = Animal.DOG
In Python 3.4 ( PEP 435 ), können Sie Enum die Basisklasse. Dadurch erhalten Sie ein wenig zusätzliche Funktionalität, die im PEP beschrieben wird. Zum Beispiel unterscheiden sich Enum-Mitglieder von Integern, und sie bestehen aus einer name
und eine value
.
from enum import Enum
class Animal(Enum):
DOG = 1
CAT = 2
print(Animal.DOG)
# <Animal.DOG: 1>
print(Animal.DOG.value)
# 1
print(Animal.DOG.name)
# "DOG"
Wenn Sie die Werte nicht eintippen wollen, verwenden Sie die folgende Abkürzung:
class Animal(Enum):
DOG, CAT = range(2)
Enum
Implementierungen können in Listen umgewandelt werden und sind iterierbar . Die Reihenfolge ihrer Mitglieder ist die Reihenfolge der Deklaration und hat nichts mit ihren Werten zu tun. Zum Beispiel:
class Animal(Enum):
DOG = 1
CAT = 2
COW = 0
list(Animal)
# [<Animal.DOG: 1>, <Animal.CAT: 2>, <Animal.COW: 0>]
[animal.value for animal in Animal]
# [1, 2, 0]
Animal.CAT in Animal
# True
Wenn Sie die numerischen Werte benötigen, ist dies der schnellste Weg:
dog, cat, rabbit = range(3)
In Python 3.x können Sie auch einen Platzhalter mit Sternchen am Ende hinzufügen, der alle verbleibenden Werte des Bereichs aufnimmt, falls es Ihnen nichts ausmacht, Speicher zu verschwenden und nicht zählen zu können:
dog, cat, rabbit, horse, *_ = range(100)
Welche Lösung für Sie die beste ist, hängt davon ab, welche Anforderungen Sie an Ihr gefälscht enum
.
Einfache Aufzählung:
Wenn Sie die enum
als nur eine Liste von Namen Identifizierung verschiedener Artikel die Lösung durch Mark Harrison (oben) ist großartig:
Pen, Pencil, Eraser = range(0, 3)
Mit einer range
ermöglicht es Ihnen auch, beliebige Startwert :
Pen, Pencil, Eraser = range(9, 12)
Wenn Sie zusätzlich zu den oben genannten Punkten verlangen, dass die Gegenstände zu einem Container und betten sie dann in eine Klasse ein:
class Stationery:
Pen, Pencil, Eraser = range(0, 3)
Um das Aufzählungselement zu verwenden, müssen Sie nun den Containernamen und den Elementnamen verwenden:
stype = Stationery.Pen
Komplexe Aufzählung:
Für lange Listen von enum oder kompliziertere Verwendungen von enum reichen diese Lösungen nicht aus. Sie können sich an das Rezept von Will Ware für Aufzählungen in Python simulieren veröffentlicht in der Python-Kochbuch . Eine Online-Version davon ist verfügbar ici .
Mehr Informationen:
PEP 354: Aufzählungen in Python hat die interessanten Details eines Vorschlags für enum in Python und warum er abgelehnt wurde.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.