पाइथन में स्ट्रिंग को एनम में बदलें


142

मुझे आश्चर्य है कि पायथन के एनम वर्ग के लिए एक स्ट्रिंग को परिवर्तित करने (डिसेरराइजिंग) का सही तरीका क्या है। लगता है जैसे getattr(YourEnumType, str)काम करता है, लेकिन मुझे यकीन नहीं है कि यह पर्याप्त सुरक्षित है।

बस अधिक विशिष्ट होने के लिए, मैं एक 'debug'स्ट्रिंग को एनम ऑब्जेक्ट में इस तरह बदलना चाहता हूं :

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

जवाबों:


214

यह कार्यक्षमता पहले से ही Enum [1] में बनाई गई है:

>>> from enum import Enum
>>> class Build(Enum):
...   debug = 200
...   build = 400
... 
>>> Build['debug']
<Build.debug: 200>

[१] आधिकारिक डॉक्स: Enum programmatic access


6
इनपुट के सैनिटाइज़ होने की स्थिति में एक फॉलबैक मूल्य के बारे में क्या? के प्रकार में कुछ Build.get('illegal', Build.debug)?
हेट्रोजनी

1
@ हेट्रोनि: Enumएक .get()विधि के साथ नहीं आती है , लेकिन आप आवश्यकतानुसार एक जोड़ सकते हैं, या बस एक आधार Enumवर्ग बना सकते हैं और हमेशा उसी से विरासत में प्राप्त कर सकते हैं।
एथन फुरमान

@ हेट्रोनि: प्रति "माफी के लिए पूछें, अनुमति के लिए नहीं" सिद्धांत के अनुसार, आप डिफ़ॉल्ट को वापस करने के लिए हमेशा की कोशिश में की को छोड़कर / (जैसे कि ईथन ने उल्लेख किया है, वैकल्पिक रूप से इसे अपने स्वयं के कार्य / विधि में लपेट सकते हैं) में पहुंच को कवर कर सकते हैं। ।
लाओगेयोड्रिट

1
माननीय उल्लेख Build('debug')
Dragonborn

2
@Dragonborn यह कॉल करने के लिए काम नहीं करेगा Build('debug')। वर्ग निर्माता रखना चाहिए मूल्य , यानी 200या 400इस उदाहरण में। नाम पारित करने के लिए आपको वर्ग कोष्ठक का उपयोग करना होगा, जैसा कि पहले से ही उत्तर कहता है।
आर्थर टक्का

17

एक अन्य विकल्प (विशेष रूप से उपयोगी है यदि आपके तार 1-1 को आपके एनम मामलों में मैप नहीं करते हैं) staticmethodआपके Enum, जैसे:

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

तब आप कर सकते हैं question_type = QuestionType.from_str('singleSelect')


1
बहुत संबंधित है, अगर आप खुद को अक्सर ऐसा करते हुए पाते हैं: pydantic-docs.helpmanual.io
driftcatcher

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

या आपको ज्ञात Enum में स्ट्रिंग बदलने की आवश्यकता है ?

class MyEnum(Enum):
    a = 'aaa'
    b = 123

print(MyEnum('aaa'), MyEnum(123))

या:

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

मेरा मतलब है कि मैं एक debugस्ट्रिंग को ऐसे python class BuildType(Enum): debug = 200 release = 400
एनाम में बदलना चाहूंगा

महान युक्तियाँ! के __dict__रूप में ही उपयोग कर रहा है getattr? मैं आंतरिक पायथन विशेषताओं के साथ नाम टकरावों के बारे में चिंता कर रहा हूं ....
व्लादिस

ओह ... हाँ यह भी ऐसा ही है getattr। मुझे नाम टकराने का कोई कारण नहीं दिखता। आप बस कक्षा के क्षेत्र के रूप में खोजशब्द निर्धारित नहीं कर सकते।
ADR

4

समस्या का मेरा जावा जैसा समाधान। आशा है कि यह किसी की मदद करता है ...

    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.upper():
                    return mm


    sim = SignInMethod.value_of('EMAIL')
    print("""TEST
    1). {0}
    2). {1}
    3). {2}
    """.format(sim, sim.name, isinstance(sim, SignInMethod)))

2

@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

-2

मैं सिर्फ यह सूचित करना चाहता हूं कि यह अजगर 3.6 में काम नहीं करता है

class MyEnum(Enum):
    a = 'aaa'
    b = 123

print(MyEnum('aaa'), MyEnum(123))

आपको डेटा को इस तरह से एक टपल के रूप में देना होगा

MyEnum(('aaa',))

EDIT: यह गलत निकला। मेरी गलती को इंगित करने के लिए एक टिप्पणीकार को श्रेय


पायथन 3.6.6 का उपयोग करते हुए, मैं इस व्यवहार को पुन: पेश नहीं कर सका। मुझे लगता है कि आपने परीक्षण करते समय गलती की होगी (मुझे पता है कि मैंने पहली बार ऐसा करते समय जाँच की थी)। यदि आप गलती से ,प्रत्येक तत्व के बाद एक (अल्पविराम) डालते हैं (जैसे कि तत्व एक सूची थे) तो यह प्रत्येक तत्व को टपल के रूप में मानता है। (यानी a = 'aaa',वास्तव में वैसा ही है a = ('aaa',))
मल्टीहंटर

आप सही कह रहे हैं, यह मेरे कोड में अलग बग था। मुझे किसी तरह लगा कि आपको ,
एनम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.