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 = 400
Given 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 NotImplementedError
Then 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 refactoring
answered 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 NotImplementedError
answered 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 |