如何检查字符串枚举中是否存在字符串?
How to check if string exists in Enum of strings?
我创建了以下枚举:
from enum import Enum
class Action(str, Enum):
NEW_CUSTOMER = "new_customer"
LOGIN = "login"
BLOCK = "block"
我也继承了 str
,所以我可以做以下事情:
action = "new_customer"
...
if action == Action.NEW_CUSTOMER:
...
我现在希望能够检查此枚举中是否有字符串,例如:
if "new_customer" in Action:
....
我尝试将以下方法添加到 class:
def __contains__(self, item):
return item in [i for i in self]
然而,当我运行这段代码时:
print("new_customer" in [i for i in Action])
print("new_customer" in Action)
我得到这个异常:
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'
您可以通过调用它来检查枚举是否包含一个值:
>>> Action('new_customer')
Action.NEW_CUSTOMER
如果您传入的对象不能保证在枚举中,您可以使用 try
块来捕获结果 ValueError
。例如,
def is_action(obj):
try:
Action(obj)
except ValueError:
return False
return True
由于 Action 是 Enum 的派生 class,我们可以利用 Enum 有一个名为 _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.
我们得到以下信息:
if "new_customer" in Action._value2member_map_: # works
接近您的要求:
if "new_customer" in Action: # doesn't work (i.e. TypeError)
我今天刚遇到这个问题;我不得不为 Python 3.8.
更改一些子包
也许下面是其他解决方案的替代方案,灵感来自出色的答案 here to a similar question, as well as @MadPhysicist's :
from enum import Enum, EnumMeta
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
测试(在 py37 或 38 中):
>>> 1 in Stuff
True
>>> Stuff.foo in Stuff
True
>>> 2 in Stuff
False
>>> 2.3 in Stuff
False
>>> 'zero' in Stuff
False
给定一个语言枚举
class Language(enum.Enum):
en = 'en'
zh = 'zh'
@classmethod
def has_member_key(cls, key):
return key in cls.__members__
print(Language.has_member_key('tu')) => False
print(Language.has_member_key('en')) => True
你也可以像在字典中一样通过括号检查枚举中的包含
class Action(Enum):
NEW_CUSTOMER = 1
LOGIN = 2
BLOCK = 3
action = 'new_customer'
try:
action = Action[action.upper()]
print("action type exists")
except KeyError:
print("action type doesn't exists")
我创建了以下枚举:
from enum import Enum
class Action(str, Enum):
NEW_CUSTOMER = "new_customer"
LOGIN = "login"
BLOCK = "block"
我也继承了 str
,所以我可以做以下事情:
action = "new_customer"
...
if action == Action.NEW_CUSTOMER:
...
我现在希望能够检查此枚举中是否有字符串,例如:
if "new_customer" in Action:
....
我尝试将以下方法添加到 class:
def __contains__(self, item):
return item in [i for i in self]
然而,当我运行这段代码时:
print("new_customer" in [i for i in Action])
print("new_customer" in Action)
我得到这个异常:
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'
您可以通过调用它来检查枚举是否包含一个值:
>>> Action('new_customer')
Action.NEW_CUSTOMER
如果您传入的对象不能保证在枚举中,您可以使用 try
块来捕获结果 ValueError
。例如,
def is_action(obj):
try:
Action(obj)
except ValueError:
return False
return True
由于 Action 是 Enum 的派生 class,我们可以利用 Enum 有一个名为 _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.
我们得到以下信息:
if "new_customer" in Action._value2member_map_: # works
接近您的要求:
if "new_customer" in Action: # doesn't work (i.e. TypeError)
我今天刚遇到这个问题;我不得不为 Python 3.8.
更改一些子包也许下面是其他解决方案的替代方案,灵感来自出色的答案 here to a similar question, as well as @MadPhysicist's
from enum import Enum, EnumMeta
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
测试(在 py37 或 38 中):
>>> 1 in Stuff
True
>>> Stuff.foo in Stuff
True
>>> 2 in Stuff
False
>>> 2.3 in Stuff
False
>>> 'zero' in Stuff
False
给定一个语言枚举
class Language(enum.Enum):
en = 'en'
zh = 'zh'
@classmethod
def has_member_key(cls, key):
return key in cls.__members__
print(Language.has_member_key('tu')) => False
print(Language.has_member_key('en')) => True
你也可以像在字典中一样通过括号检查枚举中的包含
class Action(Enum):
NEW_CUSTOMER = 1
LOGIN = 2
BLOCK = 3
action = 'new_customer'
try:
action = Action[action.upper()]
print("action type exists")
except KeyError:
print("action type doesn't exists")