2016-12-31 5 views
23

Ich frage mich, was ist die richtige Möglichkeit zum Konvertieren (Deserialisieren) einer Zeichenfolge in eine Enum-Klasse von Python. Scheint wie getattr(YourEnumType, str) macht den Job, aber ich bin mir nicht sicher, ob es sicher genug ist.Konvertieren von Zeichenfolge in Enum in Python

einfach genauer zu sein, würde Ich mag einen 'debug' String in ein Enum-Objekt wie folgt konvertieren:

class BuildType(Enum): 
    debug = 200 
    release = 400 

Antwort

39

Diese Funktionalität bereits bei Enum gebaut [1]:

>>> from enum import Enum 
>>> class Build(Enum): 
... debug = 200 
... build = 400 
... 
>>> Build['debug'] 
<Build.debug: 200> 

[1] Offizielle Dokumente: Enum programmatic access

+0

Ja, das ist, was ich gesucht habe. Ein Link zu offiziellen Dokumenten zu diesem Thema wäre nett. – Vladius

+0

@Vladius: Link hinzugefügt. –

+0

Was ist mit einem Fallback-Wert für den Fall, dass die Eingabe bereinigt werden muss? Etwas in der Art von Build.get ('illegal', Build.debug) '? – Hetzroni

1
def custom_enum(typename, items_dict): 
    class_definition = """ 
from enum import Enum 

class {}(Enum): 
    {}""".format(typename, '\n '.join(['{} = {}'.format(k, v) for k, v in items_dict.items()])) 

    namespace = dict(__name__='enum_%s' % typename) 
    exec(class_definition, namespace) 
    result = namespace[typename] 
    result._source = class_definition 
    return result 

MyEnum = custom_enum('MyEnum', {'a': 123, 'b': 321}) 
print(MyEnum.a, MyEnum.b) 

Oder Sie brauchen Zeichenfolge Enum bekannt zu konvertieren?

class MyEnum(Enum): 
    a = 'aaa' 
    b = 123 

print(MyEnum('aaa'), MyEnum(123)) 

Oder:

class BuildType(Enum): 
    debug = 200 
    release = 400 

print(BuildType.__dict__['debug']) 

print(eval('BuildType.debug')) 
print(type(eval('BuildType.debug')))  
print(eval(BuildType.__name__ + '.debug')) # for work with code refactoring 
+0

ich meine, würde Ich mag eine 'debug' String in einen Enum solcher konvertieren: ' '' Python Klasse BuildType (Enum): debug = 200 release = 400 '' ' – Vladius

+0

Gute Tipps! Ist '__dict__' gleich wie 'getattr'? Ich mache mir Sorgen über Namenskollisionen mit internen Python-Attributen .... – Vladius

+0

Oh ... ja, es ist dasselbe wie 'getattr'. Ich sehe keinen Grund für Namenskollisionen. Sie können das Schlüsselwort nicht als Klassenfeld festlegen. – ADR

0

Eine weitere Alternative (vor allem nützlich, wenn Ihre Strings nicht 1-1 zu Ihren Enum-Fällen zuordnen) ist ein staticmethod hinzuzufügen auf Ihre Enum, zB:

class QuestionType(enum.Enum): 
    MULTI_SELECT = "multi" 
    SINGLE_SELECT = "single" 

    @staticmethod 
    def from_str(label): 
     if label in ('single', 'singleSelect'): 
      return QuestionType.SINGLE_SELECT 
     elif label in ('multi', 'multiSelect'): 
      return QuestionType.MULTI_SELECT 
     else: 
      raise NotImplementedError 

Dann können Sie question_type = QuestionType.from_str('singleSelect')

Verwandte Themen