Wie soll ich am besten emulieren und / oder Enum ist in Python vermeiden? [Duplikat]
Frage
Diese Frage bereits eine Antwort hier:
- Wie kann ich ein 'Enum' in Python darstellen? 43 Antworten
Ich habe eine kleine Klasse unter Verwendung von Aufzählungen in einigen Python-Projekten zu emulieren. Gibt es einen besseren Weg, oder macht dies die am meisten Sinn für einige Situationen?
Klasse Code hier:
class Enum(object):
'''Simple Enum Class
Example Usage:
>>> codes = Enum('FOO BAR BAZ') # codes.BAZ will be 2 and so on ...'''
def __init__(self, names):
for number, name in enumerate(names.split()):
setattr(self, name, number)
Lösung
Es gibt viele gute Diskussion hier .
Andere Tipps
Aufzählungen sind für die Aufnahme in die Sprache vorgeschlagen vor, wurden aber abgelehnt (siehe http://www.python.org/dev/peps/pep-0354/ ), obwohl es bestehende Pakete könnten Sie stattdessen Ihre eigene Implementierung des Schreibens:
- Enum: http://pypi.python.org/pypi/enum
- Symboltype (nicht ganz dasselbe wie Aufzählungen, aber immer noch nützlich): http: //pypi.python.org/pypi/SymbolType
- Oder einfach eine Suche
Die häufigste Enum Fall Werte aufgezählt, die Teil eines Staates oder Strategie-Entwurfsmuster sind. Die Aufzählungen sind bestimmte Zustände oder bestimmte optionale Strategien eingesetzt werden. In diesem Fall sind sie fast immer ein wesentlicher Bestandteil von einiger Klassendefinition
class DoTheNeedful( object ):
ONE_CHOICE = 1
ANOTHER_CHOICE = 2
YET_ANOTHER = 99
def __init__( self, aSelection ):
assert aSelection in ( self.ONE_CHOICE, self.ANOTHER_CHOICE, self.YET_ANOTHER )
self.selection= aSelection
Dann wird in einem Client dieser Klasse.
dtn = DoTheNeeful( DoTheNeeful.ONE_CHOICE )
Was ich öfter sehen, ist dies in der Top-Level-Modul Kontext:
FOO_BAR = 'FOO_BAR'
FOO_BAZ = 'FOO_BAZ'
FOO_QUX = 'FOO_QUX'
... und später ...
if something is FOO_BAR: pass # do something here
elif something is FOO_BAZ: pass # do something else
elif something is FOO_QUX: pass # do something else
else: raise Exception('Invalid value for something')
Hinweis , dass die Verwendung von is
statt ==
ein Risiko hier eingeht - es wird davon ausgegangen, dass die Leute your_module.FOO_BAR
anstatt die Zeichenfolge 'FOO_BAR'
verwenden (was normal so interniert werden, dass is
wird übereinstimmen, aber das kann sicherlich nicht auf) gezählt werden, und so kann nicht sinnvoll sein, je nach Kontext.
Ein Vorteil es auf diese Weise zu tun, ist, dass durch zu dieser Zeichenfolge überall eine Referenz suchen, die gespeichert wird, ist es sofort klar, woher er kam; FOO_BAZ
ist viel weniger zweideutig als 2
.
Abgesehen davon, die andere Sache, die meine Pythonic Empfindlichkeiten re der Klasse kränkt Sie vorschlagen, ist die Verwendung von split()
. Warum passiert nicht nur in einem Tupel, Liste oder andere zählbare zu beginnen?
Der eingebaute Weg Aufzählungen zu tun ist:
(FOO, BAR, BAZ) = range(3)
, die für kleine Mengen gut funktioniert, hat aber einige Nachteile:
- Sie müssen die Anzahl der Elemente von Hand zählen
- Sie können nicht überspringen Werte
- , wenn Sie einen Namen hinzufügen, müssen Sie auch den Bereich Nummer aktualisieren
Für eine vollständige Enumeration Implementierung in Python finden Sie unter: http://code.activestate.com/recipes/67107/
Ich begann mit etwas, das viel wie S.Lott Antwort aussieht, aber ich nur ‚str‘ und ‚eq‘ (anstelle der gesamten Objektklasse) überlastete und so konnte ich den Aufzählungswert drucken und vergleichen.
class enumSeason():
Spring = 0
Summer = 1
Fall = 2
Winter = 3
def __init__(self, Type):
self.value = Type
def __str__(self):
if self.value == enumSeason.Spring:
return 'Spring'
if self.value == enumSeason.Summer:
return 'Summer'
if self.value == enumSeason.Fall:
return 'Fall'
if self.value == enumSeason.Winter:
return 'Winter'
def __eq__(self,y):
return self.value==y.value
Drucken (x) wird den Namen anstelle des Wertes ergeben und zwei Werte Federhalte einander gleich sein wird.
>>> x = enumSeason(enumSeason.Spring)
>>> print(x)
Spring
>>> y = enumSeason(enumSeason.Spring)
>>> x == y
True