在Python中将字符串转换为Enum

时间:2016-12-31 10:19:00

标签: python string serialization enums type-conversion

我想知道将字符串转换(反序列化)到Python的Enum类的正确方法是什么。好像getattr(YourEnumType, str)完成了这项工作,但我不确定它是否足够安全。

更具体地说,我想将'debug'字符串转换为Enum对象,如下所示:

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

8 个答案:

答案 0 :(得分:112)

此功能已内置于Enum [1]:

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

[1]官方文档:Enum programmatic access

答案 1 :(得分:10)

另一种替代方法(如果您的字符串不会将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')

答案 2 :(得分:2)

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

答案 3 :(得分:1)

对@rogueleaderr答案的改进:

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

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

答案 4 :(得分:1)

将您的类签名更改为:

class BuildType(str, Enum):

答案 5 :(得分:0)

类似于Java的问题解决方案。希望它可以帮助某人...

from enum import Enum, auto


class SignInMethod(Enum):
    EMAIL = auto(),
    GOOGLE = auto()

    @staticmethod
    def value_of(value) -> Enum:
        for m, mm in SignInMethod.__members__.items():
            if m == value:
                return mm


sim = SignInMethod.value_of('EMAIL')
print("""TEST
1). {0}
2). {1}
3). {2}
""".format(sim, sim.name, isinstance(sim, SignInMethod)))

答案 6 :(得分:0)

由于MyEnum['dontexist']将导致错误KeyError: 'dontexist',因此您可能希望静默失败(例如,返回None)。在这种情况下,您可以使用以下静态方法:

class Statuses(enum.Enum):
    Unassigned = 1
    Assigned = 2

    @staticmethod
    def from_str(text):
        statuses = [status for status in dir(
            Statuses) if not status.startswith('_')]
        if text in statuses:
            return getattr(Statuses, text)
        return None


Statuses.from_str('Unassigned')

答案 7 :(得分:-1)

我只想通知它在python 3.6中不起作用

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

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

您将不得不像这样以元组形式提供数据

MyEnum(('aaa',))

编辑: 事实证明这是错误的。感谢指出我的错误的评论者