KOB*_*KOB 2 python oop enums overriding class
我创建了以下枚举:
from enum import Enum
class Action(str, Enum):
NEW_CUSTOMER = "new_customer"
LOGIN = "login"
BLOCK = "block"
Run Code Online (Sandbox Code Playgroud)
我也继承自str,以便我可以做以下事情:
action = "new_customer"
...
if action == Action.NEW_CUSTOMER:
...
Run Code Online (Sandbox Code Playgroud)
我现在希望能够检查字符串是否在此 Enum 中,例如:
if "new_customer" in Action:
....
Run Code Online (Sandbox Code Playgroud)
我尝试将以下方法添加到类中:
def __contains__(self, item):
return item in [i for i in self]
Run Code Online (Sandbox Code Playgroud)
但是,当我运行此代码时:
print("new_customer" in [i for i in Action])
print("new_customer" in Action)
Run Code Online (Sandbox Code Playgroud)
我得到这个例外:
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'
Run Code Online (Sandbox Code Playgroud)
Mad*_*ist 21
您可以通过调用来检查枚举是否包含值:
>>> Action('new_customer')
Action.NEW_CUSTOMER
Run Code Online (Sandbox Code Playgroud)
如果您传入的对象不能保证位于枚举中,您可以使用块try来捕获结果ValueError。例如,
def is_action(obj):
try:
Action(obj)
except ValueError:
return False
return True
Run Code Online (Sandbox Code Playgroud)
给定一个语言枚举
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
Run Code Online (Sandbox Code Playgroud)
由于 Action 是 Enum 的派生类,因此我们可以利用 Enum 有一个名为 的成员这一事实_value2member_map_。
value2member_map是一个私有属性(即在 CPython 内部),它将值映射到名称(但仅适用于可哈希值)。然而,依赖私有属性并不是一个好主意,因为它们可以随时更改。
我们得到以下信息:
if "new_customer" in Action._value2member_map_: # works
Run Code Online (Sandbox Code Playgroud)
这接近您想要的:
if "new_customer" in Action: # doesn't work (i.e. TypeError)
Run Code Online (Sandbox Code Playgroud)
我今天刚碰到这个问题;我不得不为 Python 3.8 更改许多子包。
也许这里其他解决方案的替代方案如下,灵感来自这里对类似问题的出色回答,以及@MadPhysicist在此页面上的回答:
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
Run Code Online (Sandbox Code Playgroud)
测试(在 py37 或 38 中):
>>> 1 in Stuff
True
>>> Stuff.foo in Stuff
True
>>> 2 in Stuff
False
>>> 2.3 in Stuff
False
>>> 'zero' in Stuff
False
Run Code Online (Sandbox Code Playgroud)