Je me demande quelle est la bonne façon de convertir (désérialiser) une chaîne en classe Python's Enum. On dirait que getattr(YourEnumType, str)
fait le travail, mais je ne suis pas sûr que ce soit suffisamment sûr.
Pour être plus précis, j'aimerais convertir une 'debug'
string en un objet Enum comme ceci:
class BuildType(Enum):
debug = 200
release = 400
Cette fonctionnalité est déjà intégrée à Enum [1]:
>>> from enum import Enum
>>> class Build(Enum):
... debug = 200
... build = 400
...
>>> Build['debug']
<Build.debug: 200>
[1] Documents officiels: Enum programmatic access
Une autre alternative (particulièrement utile si vos chaînes ne mappent pas 1-1 dans votre cas d'enum) consiste à ajouter un staticmethod
à votre Enum
, par exemple:
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
Ensuite, vous pouvez faire question_type = QuestionType.from_str('singleSelect')
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)
Ou vous devez convertir une chaîne enconnu Enum?
class MyEnum(Enum):
a = 'aaa'
b = 123
print(MyEnum('aaa'), MyEnum(123))
Ou:
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
Une amélioration à la réponse de @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
Je veux juste signaler que cela ne fonctionne pas dans Python 3.6
class MyEnum(Enum):
a = 'aaa'
b = 123
print(MyEnum('aaa'), MyEnum(123))
Vous devrez donner les données comme un tuple comme ceci
MyEnum(('aaa',))
EDIT: Cela s’avère être faux. Crédits à un commentateur pour avoir signalé mon erreur
Ma solution Java au problème. J'espère que ça aide quelqu'un ...
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)))