问题
I have created the following Enum:
from enum import Enum
class Action(str, Enum):
NEW_CUSTOMER = "new_customer"
LOGIN = "login"
BLOCK = "block"
I have inherited from str
, too, so that I can do things such as:
action = "new_customer"
...
if action == Action.NEW_CUSTOMER:
...
I would now like to be able to check if a string is in this Enum, such as:
if "new_customer" in Action:
....
I have tried adding the following method to the class:
def __contains__(self, item):
return item in [i for i in self]
However, when I run this code:
print("new_customer" in [i for i in Action])
print("new_customer" in Action)
I get this exception:
True
Traceback (most recent call last):
File "/Users/kevinobrien/Documents/Projects/crazywall/utils.py", line 24, in <module>
print("new_customer" in Action)
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/enum.py", line 310, in __contains__
raise TypeError(
TypeError: unsupported operand type(s) for 'in': 'str' and 'EnumMeta'
回答1:
I just bumped into this problem today; I had to change a number of subpackages for Python 3.8.
Perhaps an alternative to the other solutions here is the following, inspired by the excellent answer here to a similar question, as well as @MadPhysicist's answer on this page:
class MetaEnum(EnumMeta):
def __contains__(cls, item):
try:
cls(item)
except ValueError:
return False
return True
class BaseEnum(Enum, metaclass=MetaEnum):
pass
class Stuff(BaseEnum):
foo = 1
bar = 5
Tests (either in py37 or 38):
>>> 1 in Stuff
True
>>> Stuff.foo in Stuff
True
>>> 2 in Stuff
False
>>> 2.3 in Stuff
False
>>> 'zero' in Stuff
False
回答2:
You can check if the enum contains a value by calling it:
>>> Action('new_customer')
Action.NEW_CUSTOMER
If the object you pass in is not guarantee to be in the enum, you can use a try
block to capture the resulting ValueError
. E.g.,
def is_action(obj):
try:
Action(obj)
except ValueError:
return False
return True
回答3:
Since Action is a derived class of Enum, we can use the fact that Enum has a member called _value2member_map_
.
value2member_map is a private attribute (i.e. Internally in CPython) tthat maps values to names(will only work for hashable values though). However, it's not a good idea to rely on private attributes as they can be changed anytime.
Reference
We get the following:
if "new_customer" in Action._value2member_map_: # works
which is close to your desired:
if "new_customer" in Action: # doesn't work (i.e. TypeError)
来源:https://stackoverflow.com/questions/63335753/how-to-check-if-string-exists-in-enum-of-strings