A more pythonic way to define an enum with dynamic members

前端 未结 3 2234
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-06 13:32

I needed to create an enum to represent the ISO country codes. The country code data comes from a json file which can be obtained from: https://github.com/lukes/ISO-3166-Cou

3条回答
  •  孤独总比滥情好
    2021-01-06 14:05

    Yes, there is a way to define the enum using the alternate declaration syntax you want. It works by hiding the "ugly" code in a metaclass derived from enum.EnumMeta. If you wished, it would also be possible to define the choices() class method there, too.

    import enum
    import json
    
    class CountryCodeMeta(enum.EnumMeta):
        def __new__(metacls, cls, bases, classdict):
            data = classdict['data']
            names = [(country['alpha-2'], int(country['country-code'])) for country in data]
    
            temp = type(classdict)()
            for name, value in names:
                temp[name] = value
    
            excluded = set(temp) | set(('data',))
            temp.update(item for item in classdict.items() if item[0] not in excluded)
    
            return super(CountryCodeMeta, metacls).__new__(metacls, cls, bases, temp)
    
    class CountryCode(enum.Enum, metaclass=CountryCodeMeta):
        data = json.load(open('slim-2.json'))
    
        @classmethod
        def choices(cls):
            return ((member.value, name) for name, member in cls.__members__.items())
    

提交回复
热议问题