简体   繁体   中英

Python Enum class membership

When using the Enum class introduced in Python 3 programmatically , how should a programmer check for Enum membership of a given integer?

Obviously, you could just ask for forgiveness but is there a membership check function that I have otherwise missed? Put more explicitly, I would like to take an integer value and check to see if its value corresponds to a valid enumeration.

from enum import Enum

class TestEnum(Enum):
    a = 0
    b = 1
    c = 2

Output:

In [13]: TestEnum(0)
Out[13]: <TestEnum.a: 0>

In [14]: TestEnum(4)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-14-09c663e9e214> in <module>()
----> 1 TestEnum(4)

C:\Anaconda3\lib\enum.py in __call__(cls, value, names, module, qualname, type, start)
    239         """
    240         if names is None:  # simple value lookup
--> 241             return cls.__new__(cls, value)
    242         # otherwise, functional API: we're creating a new Enum type
    243         return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start)

C:\Anaconda3\lib\enum.py in __new__(cls, value)
    474                 if member._value_ == value:
    475                     return member
--> 476         raise ValueError("%r is not a valid %s" % (value, cls.__name__))
    477
    478     def __repr__(self):

ValueError: 4 is not a valid TestEnum

Enum does have a __contains__ method, but it checks for member names rather than member values:

def __contains__(cls, member):
    return isinstance(member, cls) and member._name_ in cls._member_map_

Internally(in CPython) they do have a private attribute that maps values to names(will only work for hashable values though):

>>> 2 in TestEnum._value2member_map_
True
>>> 3 in TestEnum._value2member_map_
False

But it's not a good idea to rely on private attributes as they can be changed anytime, hence you can add your own method that loops over __members__.values() :

>>> class TestEnum(Enum):
...     a = 0
...     b = 1
...     c = 2
...
...     @classmethod
...     def check_value_exists(cls, value):
...         return value in (val.value for val in cls.__members__.values())
...

>>>
>>> TestEnum.check_value_exists(2)
True
>>> TestEnum.check_value_exists(3)
False

Do you mean:

from enum import Enum

class TestEnum(Enum):
    a = 3
    b = 2
    c = 1


print(TestEnum.b.name,TestEnum.b.value)

Or

print(TestEnum(2).name,TestEnum(2).value)

Output:

b 2

@classmethod def valueList(cls)->list: ''' get my list of values Return: list: the list of values ''' valueList=list(map(lambda c: c.value, cls)) return valueList @classmethod def isValid(cls,value)->bool: ''' check whether the given value is valid Args: value: the value to check Return: bool: True if the value is a valid value of this enum ''' valueList=cls.valueList() return value in valueList

The accepted answer nicely tells you about __contains__ which you can use with in for keys; but you can also simply cast the Enum to a set and check values provided you inherit from right data type (don't forget to subclass from int or str depending on your values!) :

In [29]: from enum import Enum
    ...: 
    ...: class TestEnum(int, Enum):  # See int here!
    ...:     a = 0
    ...:     b = 1
    ...:     c = 2
    ...: 

In [30]: 0 in set(TestEnum)
Out[30]: True

In [31]: TestEnum.a in TestEnum
Out[31]: True

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM