Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

enum as option in function, also add string option

When defining a function, there are several ways to limit input to a set of predefined options. I thought it would make sense to use Enum objects to achieve this. For example:

from enum import Enum, auto

class ColorOptions(Enum):
    RED = auto()
    BLUE = auto()

def color_something(color: ColorOptions):
    match color:
        case ColorOptions.RED:
            return 'rgb(1, 0, 0)'        
        case ColorOptions.BLUE:
            return 'rgb(0, 0, 1)'

# Example usage
print(color_something(ColorOptions.BLUE))  # Output: 'rgb(0, 0, 1)'

However, the following call doesn’t work:

color_something('BLUE')

To address this, I modified the function to accept both Enum members and string representations, like so:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

def color_something(color: ColorOptions | str):
    if isinstance(color, str):
        # If the string doesn't match an Enum member, let it raise an error
        color = ColorOptions[color.upper()]
    match color:
        case ColorOptions.RED:
            return 'rgb(1, 0, 0)'        
        case ColorOptions.BLUE:
            return 'rgb(0, 0, 1)'

# Example usage
print(color_something('blue'))  # Output: 'rgb(0, 0, 1)'

This works, but it feels inefficient to add this string-to-enum conversion logic to every function that uses an Enum. One option is to add a helper function, but I’m wondering if there’s built-in Enum functionality that I might be missing.

Is there a better way to handle predefined options in a function, where both Enum members and strings can be accepted without duplicating this logic everywhere?

Edit after @chepner, this limits the options in the IDE instead of str but then you have to define the options twice (in the Enum class and in the Literal part of the function).

from typing import Literal

def color_something(color: ColorOptions | Literal['red', 'blue']):
    if isinstance(color, str):
        # If the string doesn't match an Enum member, let it raise an error
        color = ColorOptions[color.upper()]
    match color:
        case ColorOptions.RED:
            return 'rgb(1, 0, 0)'        
        case ColorOptions.BLUE:
            return 'rgb(0, 0, 1)'

# Example usage
print(color_something('blue'))  # Output: 'rgb(0, 0, 1)'

>Solution :

The solution is very simple – you need to switch to StrEnum type, whose members are strings. This way string will be matched to respective enums correctly.

from enum import StrEnum, auto, Enum

class ColorOptions(StrEnum):
    RED = auto()
    BLUE = auto()

def color_something(color: ColorOptions):
    match color:
        case ColorOptions.RED:
            return 'rgb(1, 0, 0)'        
        case ColorOptions.BLUE:
            return 'rgb(0, 0, 1)'

# Example usage
print(color_something("blue"))  # Output: 'rgb(0, 0, 1)'

blue is lowercase because that is how auto() works with StrEnums. If you want uppercase matches, you can type "RED" and "BLUE" in place of auto()s

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading