programing

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

procenter 2022. 9. 28. 22:25
반응형

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

스트링을 해당 인스턴스로 변환하는 올바른 방법은 무엇입니까?Enum서브클래스?그런 것 같다getattr(YourEnumType, str)효과가 있지만 충분히 안전한지는 잘 모르겠어요

예를 들어 다음과 같은 열거형이 있다고 가정합니다.

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

문자열 지정'debug', 어떻게 하면BuildType.debug그 결과?

이 기능은 에 이미 포함되어 있습니다.

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

멤버명은 대소문자를 구분하기 때문에 사용자 입력이 변환되는 경우 대소문자가 일치하는지 확인해야 합니다.

an_enum = input('Which type of build?')
build_type = Build[an_enum.lower()]

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

문제에 대한 자바와 같은 솔루션.도움이 됐으면 좋겠는데...

from enum import Enum, auto


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

    @classmethod
    def value_of(cls, value):
        for k, v in cls.__members__.items():
            if k == value:
                return v
        else:
            raise ValueError(f"'{cls.__name__}' enum not found for '{value}'")


sim = SignInMethod.value_of('EMAIL')
assert sim == SignInMethod.EMAIL
assert sim.name == 'EMAIL'
assert isinstance(sim, SignInMethod)
# SignInMethod.value_of("invalid sign-in method")  # should raise `ValueError`
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)

또는 문자열을 알려진 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.__name__ + '.debug'))  # for work with code refactoring

@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

부터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')

클래스 시그니처를 다음과 같이 변경합니다.

class BuildType(str, Enum):

python 3.6에서는 동작하지 않는다는 것을 알려드립니다.

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

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

이렇게 데이터를 태플 형태로 제공해야 합니다.

MyEnum(('aaa',))

EDIT: 이것은 거짓으로 판명되었습니다.나의 실수를 지적한 코멘터에게 크레딧을 주다

언급URL : https://stackoverflow.com/questions/41407414/convert-string-to-enum-in-python

반응형