Idiomatic way to check if a value is inside an Enum

Viewed 41

I want to check if some string value exists in the values set of some Enum. Here is what I do:

from enum import Enum

class Color(str, Enum):

    RED = "red"
    GREEN = "green"
    YELLOW = "yellow"

s = "red"
# s = "blue"

if any(s == c.value for c in Color):
    print(Color(s))

When I checked the documentation I found that:

The EnumMeta metaclass is responsible for providing the contains(), dir(), iter() and other methods that allow one to do things with an Enum class that fail on a typical class, such as list(Color) or some_enum_var in Color

But I want something different (checking existence for values). Is there a more pythonic way to solve this?

3 Answers

In Python 3.12 you'll be able to do this directly with in:

>>> "red" in Color
<stdin>:1: DeprecationWarning: in 3.12 __contains__ will no longer raise TypeError, but will return True if
obj is a member or a member's value
...
TypeError: unsupported operand type(s) for 'in': 'str' and 'EnumMeta'

While we're waiting for that, though, one option in addition to the one you've already found is to pass your value to the constructor, which will return the appropriate enum instance if there's a matching value, and raise ValueError otherwise.

>>> Color("red")
<Color.RED: 'red'>
>>> Color("asdf")
Traceback (most recent call last):
...
ValueError: 'asdf' is not a valid Color

You can test values against _value2member_map_, a dict attribute of the Enum sub-class that maps values to member classes, if you prefer not to clutter up your code with a try-except block:

if s in Color._value2member_map_:
    print(Color(s))

Here is a slightly more aesthetic implementation based on blhsing's answer:

from enum import Enum

class Color(str, Enum):

    RED = "red"
    GREEN = "green"
    YELLOW = "yellow"

    @staticmethod
    def values():
        # provide a meaningful named getter
        return Color._value2member_map_

s = "green"
# s = "blue"

# actual use becomes more clear
if s in Color.values():
    print(Color(s))
Related