2016-12-31 32 views
23

我想知道將字符串轉換(反序列化)爲Python的Enum類的正確方法是什麼。看起來像getattr(YourEnumType, str)做這項工作,但我不確定它是否足夠安全。將字符串轉換爲Python中的Enum

只是爲了更具體,我想一個'debug'字符串轉換爲一個枚舉對象是這樣的:

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

回答

39

此功能已經內置到枚舉[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('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) 

,或者您需要字符串轉換爲稱爲枚舉?

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(枚舉): debug = 200 release = 400 ''' – Vladius

+0

偉大的提示!是否使用'__dict__'與'getattr'相同?我擔心名稱與內部Python屬性發生衝突...... – Vladius

+0

哦......是的,它和'getattr'一樣。我沒有看到名稱衝突的原因。你不能將關鍵字設置爲類的字段。 – ADR

0

另一種替代方法(尤其是有用的,如果你的字符串不映射1-1到你的枚舉案例)是增加一個staticmethodEnum,如:

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')