web-dev-qa-db-fra.com

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, j'aimerais convertir une 'debug'string en un objet Enum comme ceci:

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

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

94
Ethan Furman

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

5
rogueleaderr
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
2
ADR

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
1
javed

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

0
Sstuber

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)))
0
Mitch