5

I apologise if I'm missing anything obvious; is there a way to see if a value is in an enum which returns True if it is, False if not? For example, if I take the following enum from the python documentation,

from enum import Enum
class Colour(Enum):
     RED = 1
     GREEN = 2
     BLUE = 3

is there any way to do the following action, or an equivalent, without an exception being raised:

colour_test = "YELLOW"
if Colour[colour_test]:
    print("In enum")
else:
    print("Not in enum")
## Output wanted - "Not in enum"
## Actual output - KeyError: "YELLOW"

I know that I can use try;except statements, but I'd prefer not to in this situation as I'd like to use this conditional with some others.

  • Does this answer your question? [How to access object attribute given string corresponding to name of that attribute](https://stackoverflow.com/questions/2612610/how-to-access-object-attribute-given-string-corresponding-to-name-of-that-attrib) – KaiserKatze Jan 01 '21 at 17:19
  • @KaiserKatze yes, the getattr() method works for what I'm doing - I personally find the `x in y.__members__` dictionary solution more elegant to use though, which is what I'm now implementing over getattr() – Ace in the hole Jan 01 '21 at 17:48

5 Answers5

8

Enums have a __members__ dict that you can check:

if colour_test in Colour.__members__:
    print("In enum")
else:
    print("Not in enum")

You can alternatively use a generalized approach with hasattr, but this returns wrong results for some non-members like "__new__":

if hasattr(Colour, colour_test):
    print("In enum")
else:
    print("Not in enum")
Aplet123
  • 33,825
  • 1
  • 29
  • 55
1
if colour_test in Colour.__members__:
    print("In enum")
else:
    print("Not in enum")
scenox
  • 698
  • 7
  • 17
1

The simplest thing you can do is add try.. except block where except block will catch the KeyError.

    colour_test = "YELLOW"
    try:
         if Colour[colour_test]:
             print("In enum")
    except KeyError:
        print("Not in enum")
Divakar Patil
  • 323
  • 2
  • 11
  • 1
    "I know that I can use try;except statements, but I'd prefer not to in this situation as I'd like to use this conditional with some others." – Aplet123 Jan 01 '21 at 16:42
  • 1
    @Aplet123 so you package this into a simple function you can call from anywhere, that returns `True` or `False`. What's the problem? – Mark Ransom Jan 01 '21 at 16:56
  • @MarkRansom. The problem is that it does not meet the clear spec – Mad Physicist Jan 01 '21 at 21:18
1

If the Enums in question are yours, add a function to them:

from enum import Enum

class CustomEnum(Enum):
    #
    @classmethod
    def has_enum(cls, name):
        return name in cls.__members__

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

and in use:

>>> Color.has_enum('RED')
True

If you want to be able to do this with Enums outside your control, extract the has_enum function above:

def has_enum(cls, name):
    return name in cls.__members__

and use that:

>>> has_enum(Color, 'GREEN')
True

Disclosure: I am the author of the Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) library.

Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
0

getattr with the default argument would probably be the easiest way:

gotten = getattr(Colour, "GREEN", None)

if gotten is None:
    # Not in the enum
else:
    # gotten is in the enum

gotten will be None (or whatever you put as the third argument to getattr) if it doesn't exist.

Or, with := to make it a little more succint:

if gotten := getattr(Colour, "GREEN", None):
    # The string is in the enum
else:
    # Not in the enum

@Aplet's suggestion of hasattr is likely more appropriate here in retrospect. I like getattr with a None third argument because a lot of the time, if I'm checking if something has an attribute, I also want to use that attribute after the check. Use hasattr if you only care about whether or not it's there, but getattr is nice if you also want to use the value post-lookup.

Carcigenicate
  • 43,494
  • 9
  • 68
  • 117