36

I have an enum like this

@enum.unique
class TransactionTypes(enum.IntEnum):
    authorisation = 1
    balance_adjustment = 2
    chargeback = 3
    auth_reversal = 4

Now i am assigning a variable with this enum like this

a = TransactionTypes

I want to check for the type of 'a' and do something if its an enum and something else, if its not an enum

I tried something like this

if type(a) == enum:
    print "do enum related stuff"
else:
    print "do something else"

The problem is it is not working fine.

Prabhakar Shanmugam
  • 5,634
  • 6
  • 25
  • 36
  • `enum` is the module, why would it be equal to `type(TransactionTypes)`? Do you want `if issubclass(a, enum.Enum):`? – jonrsharpe Jul 15 '16 at 11:17
  • You could use [__members__ special attribute](https://stackoverflow.com/a/59713009/2263683) to iterate over members – Ghasem Jan 13 '20 at 08:37

5 Answers5

70

Now i am assigning a variable with this enum like this

a = TransactionTypes

I hope you aren't, because what you just assigned to a is the entire enumeration, not one of its members (such as TransactionTypes.chargeback) If that is really what you wanted to do, then the correct test would be:

if issubclass(a, enum.Enum)

However, if you actually meant something like:

a = TransactionTypes.authorisation

then the test you need is:

# for any Enum member
if isinstance(a, Enum):

or

# for a TransactionTypes Enum
if isinstance(a, TransactionTypes):
Ethan Furman
  • 63,992
  • 20
  • 159
  • 237
1

as mentioned use isinstance method to check weather an instance is of enum.Enum type or not.

A small working code for demonstration of its usage:

import enum


class STATUS(enum.Enum):
    FINISHED = enum.auto()
    DELETED = enum.auto()
    CANCELLED = enum.auto()
    PENDING = enum.auto()


if __name__ == "__main__":
    instance = STATUS.CANCELLED

    if isinstance(instance, enum.Enum):
        print('name : ', instance.name, ' value : ', instance.value)
    else:
        print(str(instance))

Output:

name :  CANCELLED  value :  3
Udesh
  • 2,415
  • 2
  • 22
  • 32
0

reliable solution:

from enum import IntEnum
from collections import Iterable

def is_IntEnum(obj):
    try:
        return isinstance(obj, Iterable) and isinstance (next(iter(obj)), IntEnum)
    except:
        return False # Handle StopIteration, if obj has no elements
iperov
  • 455
  • 7
  • 8
  • What did you find unreliable about the accepted answer? – Ethan Furman Mar 04 '21 at 15:13
  • 1
    @EthanFurman `from enum import IntEnum, Enum` `class MyEnum(IntEnum): FOO_BAR = 0 JOHN_DOE = 1 ` `print( isinstance(MyEnum, Enum) ) # False` `print( isinstance(MyEnum, IntEnum) ) # False` – iperov Mar 05 '21 at 13:51
  • You are using the wrong comparison: `MyEnum` is a type, and to check if one type is a subclass of another type you use `issubclass`; so your example should be `issubclass(MyEnum, Enum)` and `issubclass(MyEnum, IntEnum)`, both of which would return `True`. `isinstance` would be appropriate for `isinstance(MyEnum.JOHN_DOE, IntEnum)`. – Ethan Furman Mar 05 '21 at 14:43
  • Your answer uses `issubclass` which will raise an error on not a class object. List and enum are both iterables, both can be used as iterable list of choices for something. Therefore, your answer is not reliable solution. My answer may be not beatiful, but it is reliable. Thus your minus to me is not justified. – iperov Mar 06 '21 at 10:10
  • In my experience using an `isinstance()` check with subclasses has always been an error: either `issubclass()` was the correct choice, or I was comparing the wrong objects. Your "reliable" method would hide those bugs. If you can add an example to your answer where either a `list` or an `IntEnum` member would be appropriate values, I will happily remove my downvote. – Ethan Furman Mar 07 '21 at 19:46
0

I thought I`ve got a ugly way. eg:

print(o.__class__.__class__) 

Output:

<enum.EnumMeta>
S.B
  • 13,077
  • 10
  • 22
  • 49
lsfzem
  • 11
  • 1
  • 2
    Welcome to Stack Overflow! I do not see how this answers the question at the top of this page, but it should. Please [edit] according to [answer] or delete the answer. Otherwise it risks being flagged as "not an answer" and being deleted. – Yunnosch Sep 20 '21 at 20:11
0

There are already good answers here but in case of it might be useful for some people out there I wanted to stretch the question a little further and created a simple example to propose a humble solution to help caller function who does maybe little knowledge about Enum solve problem of sending arguments to functions that take only Enum as a parameter by proposing a converter just below the file that Enum was created.

from enum import Enum
from typing import Union


class Polygon(Enum):
    triangle: 3
    quadrilateral: 4
    pentagon: 5
    hexagon: 6
    heptagon: 7
    octagon: 8
    nonagon: 9
    decagon: 10



def display(polygon: Polygon):
    print(f"{polygon.name} : {polygon.value} ")


def do_something_with_polygon(polygon: Polygon):
    """This one is not flexible cause it only accepts a Polygon Enum it does not convert"""

    """ if parameter is really a Polygon Enum we are ready to do stuff or We get error """
    display(polygon)


def do_something_with_polygon_more_flexible(maybe_polygon_maybe_not: Union[Polygon, int, str]):
    """ it will be more convenient function by taking extra parameters and converting"""
    if isinstance(maybe_polygon_maybe_not, Enum):
        real_polygon = maybe_polygon_maybe_not
    else:
        real_polygon = get_enum_with_value(int(maybe_polygon_maybe_not), Polygon, Polygon.quadrilateral)

    """ now we are ready to do stuff """
    display(real_polygon)


def get_enum_with_value(key: int, enum_: any, default_value: Enum):
    """ this function will convert int value to Enum that corresponds checking parameter key """

    # create a dict with all values and name of Enum
    dict_temp = {x.value: x for x in
                 enum_}  # { 3 : Polygon.triangle , 4 :Polygon.quadrilateral , 5 : Polygon.pentagon , ...  }

    # if key exists for example 6 or '6' that comes to do_something_with_polygon_more_flexible
    # returns Polygon.hexagon
    enum_value = dict_temp.get(key, None)
    # if key does not exist we get None
    if not enum_value:
        ...  # if key does not exist we return default value (Polygon.quadrilateral)
        enum_value = default_value  # Polygon.quadrilateral

    return enum_value
Sermet Pekin
  • 357
  • 2
  • 6