Wie konvertiere ich int in Enum in Python?

89

Verwenden der neuen Enum-Funktion (über Backport enum34 ) mit Python 2.7.6.

Wie kann ich angesichts der folgenden Definition ein int in den entsprechenden Enum-Wert konvertieren?

from enum import Enum

class Fruit(Enum):
    Apple = 4
    Orange = 5
    Pear = 6

Ich weiß, dass ich eine Reihe von if-Anweisungen von Hand erstellen kann, um die Konvertierung durchzuführen, aber gibt es eine einfache pythonische Methode zum Konvertieren? Grundsätzlich möchte ich eine Funktion ConvertIntToFruit (int), die einen Aufzählungswert zurückgibt.

Mein Anwendungsfall ist, dass ich eine CSV-Datei mit Datensätzen habe, in der ich jeden Datensatz in ein Objekt einlese. Eines der Dateifelder ist ein ganzzahliges Feld, das eine Aufzählung darstellt. Während ich das Objekt auffülle, möchte ich dieses ganzzahlige Feld aus der Datei in den entsprechenden Enum-Wert im Objekt konvertieren.

Benutzer
quelle

Antworten:

157

Sie "nennen" die EnumKlasse:

Fruit(5)

zu verwandeln 5in Fruit.Orange:

>>> from enum import Enum
>>> class Fruit(Enum):
...     Apple = 4
...     Orange = 5
...     Pear = 6
... 
>>> Fruit(5)
<Fruit.Orange: 5>

Aus dem Abschnitt Programmatischer Zugriff auf Aufzählungselemente und ihre Attribute in der Dokumentation:

Manchmal ist es nützlich, programmgesteuert auf Mitglieder in Aufzählungen zuzugreifen (dh Situationen, in denen dies Color.rednicht der Fall ist, weil die genaue Farbe zum Zeitpunkt des Programmschreibens nicht bekannt ist). Enumermöglicht einen solchen Zugriff:

>>> Color(1)
<Color.red: 1>
>>> Color(3)
<Color.blue: 3>

In einem verwandten Hinweis: Um einen Zeichenfolgenwert zuzuordnen, der den Namen eines Enum-Mitglieds enthält, verwenden Sie das Abonnement:

>>> s = 'Apple'
>>> Fruit[s]
<Fruit.Apple: 4>
Martijn Pieters
quelle
Vielen Dank, ich habe das gerade erhalten, als ich die Dokumentation noch einmal gelesen habe. War mir beim ersten Durchblättern nicht klar. Außerdem habe ich gerade versucht, eine Zeichenfolge zu verwenden, und es ist schön zu sehen, dass dies funktioniert, wenn der Aufzählungswert ebenfalls eine Zeichenfolge ist und ich einen beliebigen Objektwert annehme.
Benutzer
Sehr gut, daher erfolgt die Konvertierung nach Wert. Gibt es ein Analogon für einen anderen Namen als ein Listenverständnis, um durch die Aufzählungsliste zu filtern und die Übereinstimmung mit den Namensattributen zu ermitteln?
Jxramos
4
@jxramos folgen Sie dem Dokumentationslink in meiner Antwort, er wird dort ausdrücklich behandelt. Verwenden Sie den Artikelzugriff : Fruit['Orange'].
Martijn Pieters
Bingo, sehr großartig! Ich suchte die Seite für convert, coerceund castaber nichts getroffen. Sieht aus wie die Magie war access enum members by name, use item access. Perfecto, vielen Dank, ich werde meinen Code mit dieser Syntax bereinigen.
Jxramos
Noch cooler ist, dass ich das Zeug gerne verwenden kann "foobar" in Fruit.__members__, um die Mitgliedschaft zu testen und sogar abzureißen Fruit.get( 'foobar', Fruit.Orange ), um das Standard-Enum-Aroma zu erhalten. Mein Code sieht viel einfacher aus, wenn ich all diese Zubehör-Suchgerüste entferne, die ich zuvor angelegt habe.
Jxramos
1

Ich denke, es ist in einfachen Worten, den intWert Enumdurch Aufrufen umzuwandeln EnumType(int_value), danach Zugriff nameauf das EnumObjekt:

my_fruit_from_int = Fruit(5) #convert to int
fruit_name = my_fruit_from_int.name #get the name
print(fruit_name) #Orange will be printed here

Oder als Funktion:

def convert_int_to_fruit(int_value):
    try:
        my_fruit_from_int = Fruit(int_value)
        return my_fruit_from_int.name
    except:
        return None
Ali Ezzat Odeh
quelle
-1

Ich wollte etwas Ähnliches, damit ich von einer einzelnen Referenz aus auf jeden Teil des Wertepaars zugreifen kann. Die Vanille-Version:

#!/usr/bin/env python3


from enum import IntEnum


class EnumDemo(IntEnum):
    ENUM_ZERO       = 0
    ENUM_ONE        = 1
    ENUM_TWO        = 2
    ENUM_THREE      = 3
    ENUM_INVALID    = 4


#endclass.


print('Passes')
print('1) %d'%(EnumDemo['ENUM_TWO']))
print('2) %s'%(EnumDemo['ENUM_TWO']))
print('3) %s'%(EnumDemo.ENUM_TWO.name))
print('4) %d'%(EnumDemo.ENUM_TWO))
print()


print('Fails')
print('1) %d'%(EnumDemo.ENUM_TWOa))

Der Fehler löst erwartungsgemäß eine Ausnahme aus.

Eine robustere Version:

#!/usr/bin/env python3


class EnumDemo():


    enumeration =   (
                        'ENUM_ZERO',    # 0.
                        'ENUM_ONE',     # 1.
                        'ENUM_TWO',     # 2.
                        'ENUM_THREE',   # 3.
                        'ENUM_INVALID'  # 4.
                    )


    def name(self, val):
        try:

            name = self.enumeration[val]
        except IndexError:

            # Always return last tuple.
            name = self.enumeration[len(self.enumeration) - 1]

        return name


    def number(self, val):
        try:

            index = self.enumeration.index(val)
        except (TypeError, ValueError):

            # Always return last tuple.
            index = (len(self.enumeration) - 1)

        return index


#endclass.


print('Passes')
print('1) %d'%(EnumDemo().number('ENUM_TWO')))
print('2) %s'%(EnumDemo().number('ENUM_TWO')))
print('3) %s'%(EnumDemo().name(1)))
print('4) %s'%(EnumDemo().enumeration[1]))
print()
print('Fails')
print('1) %d'%(EnumDemo().number('ENUM_THREEa')))
print('2) %s'%(EnumDemo().number('ENUM_THREEa')))
print('3) %s'%(EnumDemo().name(11)))
print('4) %s'%(EnumDemo().enumeration[-1]))

Bei nicht korrekter Verwendung wird dadurch vermieden, dass eine Ausnahme erstellt wird, und stattdessen wird eine Fehleranzeige zurückgegeben. Ein pythonischerer Weg, dies zu tun, wäre, "Keine" zurückzugeben, aber meine spezielle Anwendung verwendet den Text direkt.

user3355323
quelle
Warum nicht einfach die Methoden __int__und __str__in einer Enum-Instanz definieren?
Tim