5 Best Ways to Look Up Enum by String Value in Python

πŸ’‘ Problem Formulation: Python’s Enum class is a powerful tool for creating enumerations, which are a set of symbolic names bound to unique, constant values. Often, there is a need to look up an enum member by its string value. This article addresses this common task by providing five effective methods for retrieving enum elements given their string representation. For instance, if we have an enum Color with a member RED = 1, we want to be able to find Color.RED by the string “RED”.

Method 1: Using the getattr() Function

The getattr() function in Python is used to retrieve the value of the named attribute of an object dynamically. This method is particularly useful in cases where the name of the attribute to be accessed is not known until runtime.

Here’s an example:

from enum import Enum

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

color_name = "RED"
color_enum = getattr(Color, color_name, None)

Output: Color.RED

This snippet demonstrates the use of getattr() to fetch an enum member by string. If the attribute does not exist, it returns None, preventing an AttributeError. This is a straightforward and readable method.

Method 2: Enum’s __members__ Mapping

The __members__ attribute of the Enum class is a mapping of member names to their respective members. This mapping can be used to perform lookups by string value directly.

Here’s an example:

from enum import Enum

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

color_name = "RED"
color_enum = Color.__members__.get(color_name)

Output: Color.RED

This method utilizes the __members__ mapping to find an enum member. It is a simple and direct way to access enum values, but be careful as directly accessing dunder (double underscore) attributes is generally discouraged in Python.

Method 3: Using a Custom Function

A custom function can be written to enhance readability and encapsulate the logic required for converting a string value to an Enum member, making it reusable in different parts of your codebase.

Here’s an example:

from enum import Enum

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

def string_to_enum(s):
    return Color.__members__.get(s)

color_name = "RED"
color_enum = string_to_enum(color_name)

Output: Color.RED

This approach creates a dedicated function that simply wraps the logic for using the __members__ mapping, providing better abstraction and the opportunity to handle errors or special cases more cleanly.

Method 4: Using a Dictionary Comprehension

A dictionary comprehension can be employed to create a mapping from string values to Enum members, which can then be used for lookups. This method can pre-generate the mapping which is useful if multiple lookups will be performed.

Here’s an example:

from enum import Enum

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

name_to_enum = {member.name: member for member in Color}
color_enum = name_to_enum.get("RED")

Output: Color.RED

This code snippet demonstrates the creation of a mapping from the names of the enumeration members to the members themselves. This lookup table is useful when there are going to be multiple lookups.

Bonus One-Liner Method 5: Using a Lambda Function

A lambda function coupled with next() and a generator expression can provide an inline method for retrieving an enum member by its string value. This method is compact and functional.

Here’s an example:

from enum import Enum

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

color_enum = next((member for name, member in Color.__members__.items() if name == "RED"), None)

Output: Color.RED

This concise snippet uses a lambda function to iterate over the __members__.items() of the enum and selects the member if its name matches the input string. In case no match is found, it returns None.

Summary/Discussion

  • Method 1: Using getattr(). Quick and clean for a one-time lookup or when the attribute name to be accessed might change. Care should be taken to provide a default value to avoid AttributeError.
  • Method 2: Enum’s __members__ Mapping. Direct but less Pythonic since it involves accessing a protected member of the class. Not the best practice but is performant for one-time lookups.
  • Method 3: Using a Custom Function. Encapsulates logic, enhancing readability and reusability. This is a cleaner approach, allowing for extension and error handling.
  • Method 4: Using a Dictionary Comprehension. Pre-generates a mapping which can be more efficient for repeated lookups but might be overkill for single use-cases.
  • Bonus One-Liner Method 5: Using a Lambda Function. A succinct, functional approach for inline retrieval of enum members; however, it may be less readable to those unfamiliar with lambdas and generators.