web-dev-qa-db-ja.com

Pythonで文字列をEnumに変換します

文字列をPythonのEnumクラスに変換(デシリアライズ)する正しい方法は何でしょうか。 getattr(YourEnumType, str)が仕事をしているようですが、それが十分に安全かどうかはわかりません。

具体的には、'debug'stringを次のようなEnumオブジェクトに変換したいと思います。

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

この機能は既にEnumに組み込まれています[1]:

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

[1]公式ドキュメント: Enum programmatic access

120
Ethan Furman

別の代替方法(特に、文字列が列挙型のケースに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')を行うことができます

12
rogueleaderr
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)

または、文字列をknown 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.__+ '.debug'))  # for work with code refactoring
2
ADR

@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
1
javed

python 3.6では機能しないことを通知したいだけです

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

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

このようなタプルとしてデータを提供する必要があります

MyEnum(('aaa',))

編集:これは偽であることが判明。私の間違いを指摘してくれたコメンターの功績

0
Sstuber

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)))
0
Mitch