পাইথনের এনামে স্ট্রিং রূপান্তর করুন


141

আমি আশ্চর্য হয়েছি যে একটি স্ট্রিংটিকে পাইথনের এনাম ক্লাসে রূপান্তর করার (deserialization) সঠিক উপায় কী। getattr(YourEnumType, str)কাজটি দেখে মনে হচ্ছে তবে এটি যথেষ্ট নিরাপদ কিনা তা আমি নিশ্চিত নই।

আরও নির্দিষ্ট করে বলতে গেলে, আমি 'debug'স্ট্রিংটিকে এনুম অবজেক্টে রূপান্তর করতে চাই :

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

উত্তর:


213

এই কার্যকারিতা ইতিমধ্যে এনাম [1] এ অন্তর্নির্মিত:

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

[1] অফিসিয়াল ডক্স: Enum programmatic access


6
ইনপুটটি স্যানিটাইজ করা দরকার হলে ফ্যালব্যাক মানটির কী হবে? সাজানোর কিছু আছে Build.get('illegal', Build.debug)?
হেটজ্রোনি

1
@ হিটজ্রোনি: Enumকোনও .get()পদ্ধতি নিয়ে আসে না , তবে আপনি প্রয়োজন হিসাবে একটি যুক্ত করতে পারেন বা কেবল একটি বেস Enumক্লাস তৈরি করতে পারেন এবং সর্বদা এটির উত্তরাধিকারী হতে পারেন।
ইথান ফুরম্যান

@ হিটজ্রোনি: "ক্ষমার জন্য অনুরোধ করুন, অনুমতি চাইবেন না" নীতি অনুসারে আপনি ডিফল্ট ফিরিয়ে দেওয়ার জন্য কী-এররার ধারাটি বাদ দিয়ে সর্বদা চেষ্টা চালিয়ে যেতে পারবেন (এবং যেমন ইথান উল্লেখ করেছেন, এটি আপনার নিজস্ব ফাংশন / পদ্ধতিতে মোড়লে) ।
Laogeodritt

1
সম্মানজনক উল্লেখ Build('debug')
ড্রাগনোর্ন

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)

অথবা আপনার পরিচিত এনামে স্ট্রিং রূপান্তর করতে হবে ?

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। নাম সংঘর্ষের কোনও কারণ আমি দেখতে পাচ্ছি না। আপনি ক্লাসের ক্ষেত্র হিসাবে কীওয়ার্ডটি সেট করতে পারবেন না।
এডিআর

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

@Roogleaderr এর উত্তরের উন্নতি:

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

সম্পাদনা: এটি মিথ্যা বলে প্রমাণিত হয়েছে। আমার ভুল উল্লেখ করার জন্য একজন মন্তব্যকারীকে ক্রেডিট করুন


পাইথন ৩.6..6 ব্যবহার করে, আমি এই আচরণটি পুনরুত্পাদন করতে পারিনি। আমি মনে করি পরীক্ষার সময় আপনি ভুল করে থাকতে পারেন (আমি জানি আমি এটি পরীক্ষার সময় প্রথমবার করেছি)। যদি আপনি ঘটনাক্রমে ,প্রতিটি উপাদানটির পরে একটি (কমা) রাখেন (যেন উপাদানগুলি একটি তালিকা ছিল) তবে এটি প্রতিটি উপাদানকে একটি টিউপল হিসাবে বিবেচনা করে। (যেমন a = 'aaa',বাস্তবে একই a = ('aaa',))
মাল্টিহান্টার

আপনি ঠিক বলেছেন, এটি আমার কোডে আলাদা বাগ ছিল was আমি একরকম ভেবেছিলাম যে ,
এনামকে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.