What's the correct way to convert a string to a corresponding instance of an Enum subclass? Seems like getattr(YourEnumType, str) does the job, but I'm not sure if it's safe enough.
As an example, suppose I have an enum like
class BuildType(Enum): debug = 200 release = 400Given the string 'debug', how can I get BuildType.debug as a result?
asked Dec 31, 2016 at 10:18
1
This functionality is already built in to Enum:
>>> from enum import Enum >>> class Build(Enum): ... debug = 200 ... build = 400 ... >>> Build['debug'] <Build.debug: 200>The member names are case sensitive, so if user-input is being converted you need to make sure case matches:
an_enum = input('Which type of build?') build_type = Build[an_enum.lower()]
Neuron
4,5784 gold badges32 silver badges53 bronze badges
answered Dec 31, 2016 at 15:06
Ethan FurmanEthan Furman
59.6k18 gold badges146 silver badges220 bronze badges
8
Another alternative (especially useful if your strings don't map 1-1 to your enum cases) is to add a staticmethod to your Enum, e.g.:
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 NotImplementedErrorThen you can do question_type = QuestionType.from_str('singleSelect')
answered Mar 1, 2018 at 23:51
rogueleaderrrogueleaderr
4,4822 gold badges32 silver badges40 bronze badges
2
My Java-like solution to the problem. Hope it helps someone...
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`answered Jun 12, 2019 at 17:07
MitchMitch
1,4401 gold badge15 silver badges17 bronze badges
1
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 do you need to convert string to known Enum?
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 refactoringanswered Dec 31, 2016 at 11:27
ADRADR
1,2099 silver badges20 bronze badges
3
An improvement to the answer of @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 NotImplementedErroranswered Jun 8, 2019 at 9:33
JavedJaved
5,6884 gold badges42 silver badges68 bronze badges
4
Since MyEnum['dontexist'] will result in error KeyError: 'dontexist', you might like to fail silently (eg. return None). In such case you can use the following static method:
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')answered Oct 17, 2020 at 20:35
nmenme
1,01510 silver badges8 bronze badges
Change your class signature to this:
class BuildType(str, Enum):
Robson
7865 gold badges23 silver badges39 bronze badges
answered Apr 7, 2021 at 9:22
1
I just want to notify this does not work in 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
answered Oct 23, 2018 at 18:39
2