2016-12-31 2 views
23

Интересно, какой правильный способ преобразования (десериализации) строки в класс Enum Python. Кажется, что getattr(YourEnumType, str) выполняет эту работу, но я не уверен, насколько это достаточно безопасно.Преобразование строки в Enum в Python

Просто чтобы быть более конкретным, я хотел бы преобразовать 'debug' строку в объект Enum, как это:

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

ответ

39

Эта функция уже встроена в Enum [1]:

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

[1] Официальные документы: Enum programmatic access

+0

Да, это то, что я искал. Ссылка на официальные документы по этому вопросу была бы приятной. – Vladius

+0

@ Vladius: Добавлена ​​ссылка. –

+0

Как насчет резервной стоимости в случае необходимости дезинфекции входа? Что-то вроде «Build.get (« незаконный »,« 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) 

Или вам нужно преобразовать строку в известной Enum?

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

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

Или:

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

я имею в виду, я хотел бы преобразовать 'debug' строку в перечисление такой: ' '' питон класса BuildType (Enum): debug = 200 release = 400 '' ' – Vladius

+0

Отличные советы! Использует '__dict__' то же самое, что' getattr'? Я беспокоюсь о столкновениях имен с внутренними атрибутами Python .... – Vladius

+0

О ... да, это так же, как 'getattr'. Я не вижу причин для столкновений имен. Вы просто не можете установить ключевое слово как поле класса. – ADR

0

Другой вариант (особенно полезно, если ваши строки не отображают 1-1 для ваших случаев перечисления) заключается в том, чтобы добавить staticmethod к вашему Enum, например:

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 

Затем вы можете сделать question_type = QuestionType.from_str('singleSelect')

Смежные вопросы