246 votes

Convertir une chaîne en Enum en Python

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, je voudrais convertir une chaîne 'debug' en un objet Enum comme ceci:

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

402voto

Ethan Furman Points 12683

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

32voto

rogueleaderr Points 439

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

12voto

ADR Points 587
 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 avez besoin de convertir une chaîne en Enum connu ?

 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.__name__ + '.debug'))  # for work with code refactoring
 

-1voto

Sstuber Points 9

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 sous forme de tuple comme ceci

 MyEnum(('aaa',))
 

EDIT: Cela se révèle être faux. Crédits à un commentateur pour avoir signalé mon erreur

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X