2016-12-31 12 views
23

Tôi tự hỏi cách chính xác để chuyển đổi (deserializing) một chuỗi thành lớp Enum của Python là gì. Có vẻ như getattr(YourEnumType, str) thực hiện công việc, nhưng tôi không chắc liệu nó có đủ an toàn hay không.Chuyển chuỗi thành Enum bằng Python

Chỉ cần được cụ thể hơn, tôi muốn chuyển đổi một chuỗi 'debug' đến một đối tượng Enum như thế này:

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

Trả lời

39

Chức năng này đã được tích hợp sẵn trong Enum [1]:

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

[1] tài liệu chính thức: Enum programmatic access

+0

Vâng, đây là những gì tôi đang tìm kiếm. Một liên kết đến các tài liệu chính thức về vấn đề đó sẽ tốt đẹp. – Vladius

+0

@Vladius: Đã thêm liên kết. –

+0

Điều gì về giá trị dự phòng trong trường hợp đầu vào cần được khử trùng? Một cái gì đó trong loại 'Build.get ('bất hợp pháp', 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) 

Hoặc bạn cần phải chuyển đổi chuỗi để biết Enum?

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

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

Hoặc:

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

tôi có nghĩa là tôi muốn chuyển đổi một 'chuỗi debug' đến một enum như vậy: '' 'python lớp BuildType (Enum): debug = 200 release = 400 '' ' – Vladius

+0

Mẹo tuyệt vời! Đang sử dụng '__dict__' giống như' getattr'? Tôi đang lo lắng về xung đột tên với các thuộc tính Python nội bộ .... – Vladius

+0

Ồ ... có nó giống như 'getattr'. Tôi không thấy lý do gì cho việc va chạm tên. Bạn không thể đặt từ khóa làm trường của lớp. – ADR

0

Một lựa chọn khác (đặc biệt là hữu ích nếu các chuỗi của bạn không ánh xạ 1-1 đến các trường hợp enum của bạn) là thêm staticmethod để Enum của bạn, ví dụ:

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 

Sau đó, bạn có thể làm question_type = QuestionType.from_str('singleSelect')

Các vấn đề liên quan