如何检查字符串枚举中是否存在字符串?

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)


Sha*_*oui 8

给定一个语言枚举

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)

  • 此代码不起作用,因为您检查的字符串不是“en”、“zh”字符串值,而是枚举键名称。保留值并将枚举键名称更改为英文、中文,然后尝试您的代码是否有效? (2认同)
  • 是的,您的代码是偶然运行的,因为枚举键名称和键值相同。正如我所说,尝试使用重命名的密钥的不同版本。用你的方法尝试这个枚举: ` class Language(Enum): English = 'en' Chinese = 'zh' ` 问题是关于检查 enum 内的 enum str 值,而不是 enum 键名称。 (2认同)

Dar*_*ylG 6

由于 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)


Pie*_*e D 5

我今天刚碰到这个问题;我不得不为 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)