在 Python 中将字符串转换为枚举

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41407414/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 00:54:07  来源:igfitidea点击:

Convert string to Enum in Python

pythonstringserializationenumstype-conversion

提问by Vladius

I wonder what's the correct way of converting (deserializing) a string to a Python's Enum class. Seems like getattr(YourEnumType, str)does the job, but I'm not sure if it's safe enough.

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

Just to be more specific, I would like to convert a 'debug'string to an Enum object like this:

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

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

回答by Ethan Furman

This functionality is already built in to Enum [1]:

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

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

[1] Official docs: Enum programmatic access

[1] 官方文档: Enum programmatic access

回答by rogueleaderr

Another alternative (especially useful if your strings don't map 1-1 to your enum cases) is to add a staticmethodto your Enum, e.g.:

另一种替代方法(如果您的字符串没有将 1-1 映射到您的枚举情况,则特别有用)是将 a 添加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

Then you can do question_type = QuestionType.from_str('singleSelect')

然后你可以做 question_type = QuestionType.from_str('singleSelect')

回答by ADR

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)

Or you need to convert string to knownEnum?

或者您需要将字符串转换为已知的枚举?

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

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

Or:

或者:

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

回答by Mitch

My Java-like solution to the problem. Hope it helps someone...

我的类似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.upper():
                    return mm


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

回答by javed

An improvement to the answer of @rogueleaderr :

对@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

回答by Sstuber

I just want to notify this does not work in python 3.6

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

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

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

You will have to give the data as a tuple like this

您必须将数据作为这样的元组提供

MyEnum(('aaa',))

EDIT: This turns out to be false. Credits to a commenter for pointing out my mistake

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