개발/Python

Python에서 문자열을 Enum으로 변환

MinorMan 2021. 1. 12. 10:22
반응형

<질문>

문자열을 Python의 Enum 클래스로 변환 (역 직렬화)하는 올바른 방법이 무엇인지 궁금합니다. 것 같아getattr(YourEnumType, str)일을하지만 충분히 안전한지 잘 모르겠습니다.

좀 더 구체적으로 말하자면'debug'다음과 같이 Enum 객체에 문자열을 추가합니다.

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

<답변1>

이 기능은 이미 Enum [1]에 내장되어 있습니다.

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

[1] 공식 문서 :Enum programmatic access


<답변2>

또 다른 대안 (특히 문자열이 열거 형 케이스에 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')


<답변3>

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

<답변4>

문제에 대한 내 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)))

<답변5>

@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

<답변6>

이후MyEnum['dontexist']오류가 발생합니다KeyError: 'dontexist', 당신은 조용히 실패하고 싶을 수도 있습니다 (예 : return 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>

나는 이것이 파이썬 3.6에서 작동하지 않는다는 것을 알리고 싶습니다.

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

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

다음과 같은 튜플로 데이터를 제공해야합니다.

MyEnum(('aaa',))

편집 : 이것은 거짓으로 판명되었습니다. 내 실수를 지적한 댓글 작성자의 크레딧

반응형