KDecker
KDecker

Reputation: 7128

Getting enum object from string when enum values are tuples?

I have Enum of the form

class ItemType(Enum):
    ITEM1 = ('Desc1', AnotherEnum.ONE)
    ITEM2 = ('Desc2', AnotherEnum.TWO)

and I am trying to instantiate an object of the type ItemType from a JSON string.

For example I would like to get the ItemType that logically represents the string 'Desc1'. If the enum values were of the form ITEM1 = 'Desc1' I could simple do ItemType('Desc1'). But in the current form I am not sure how I could achieve the lookup method.

Is there a way to do this?

Upvotes: 4

Views: 4221

Answers (1)

Thijs van Dien
Thijs van Dien

Reputation: 6616

An Enum is just a class, so how about an alternate constructor? It's the most explicit.

class ItemType(Enum):
    ITEM1 = ('Desc1', AnotherEnum.ONE)
    ITEM2 = ('Desc2', AnotherEnum.TWO)
    
    @classmethod
    def from_description(cls, description):
        for item in cls:
            if item.value[0] == description:
                return item
        raise ValueError("%r is not a valid %s description" % (description, cls.__name__))

You can then do ItemType.from_description('Desc1').

Alternatively, if you want ItemType('Desc1') to just work, as of Python 3.6 you can implement _missing_:

class ItemType(Enum):
    ITEM1 = ('Desc1', AnotherEnum.ONE)
    ITEM2 = ('Desc2', AnotherEnum.TWO)
    
    @classmethod
    def _missing_(cls, value):
        for item in cls:
            if item.value[0] == value:
                return item
        return super()._missing_(value)

I'd base my choice on whether looking up by description is a natural thing to do or not. If it's specific to translating JSON, rather stick with the alternate constructor. Otherwise, sure, go for this second option. However, in that case I'd wonder if the value is the best place to store the related AnotherEnum. Maybe instead you should have a method to_another_enum(), an alternate constructor on AnotherEnum, or both...?

Upvotes: 8

Related Questions