使用Python Enum类,有没有办法测试Enum是否包含特定的int值而不使用try/catch?
使用以下课程:
from enum import Enum
class Fruit(Enum):
Apple = 4
Orange = 5
Pear = 6
Run Code Online (Sandbox Code Playgroud)
如何测试值6(返回true)或值7(返回false)?
hir*_*ist 73
你可以列出这样的值:
print(Fruit._value2member_map_)
# {4: <Fruit.Apple: 4>, 5: <Fruit.Orange: 5>, 6: <Fruit.Pear: 6>}
Run Code Online (Sandbox Code Playgroud)
或者(可能更好):使用Enum
; 该_value2member_map_
运营商将更加有效:
5 in Fruit._value2member_map_ # True
7 in Fruit._value2member_map_ # False
Run Code Online (Sandbox Code Playgroud)
然后测试
values = [item.value for item in Fruit] # [4, 5, 6]
Run Code Online (Sandbox Code Playgroud)
您也可以将此作为方法添加到您的班级:
values = set(item.value for item in Fruit) # {4, 5, 6}
Run Code Online (Sandbox Code Playgroud)
如果你想测试名字(而不是价值),Reda Maachi的答案涵盖了我会做什么.
Ber*_*pac 19
有一种方法可以让所有枚举都能够检查项目是否存在:
import enum
class MyEnumMeta(enum.EnumMeta):
def __contains__(cls, item):
return item in [v.value for v in cls.__members__.values()]
class MyEnum(enum.Enum, metaclass=MyEnumMeta):
FOO = "foo"
BAR = "bar"
Run Code Online (Sandbox Code Playgroud)
现在你可以做一个简单的检查:
>>> "foo" in MyEnum
True
Run Code Online (Sandbox Code Playgroud)
如果所有枚举的值总是相同的类型,它甚至可以变得更简单——例如字符串:
import enum
class MyEnumMeta(enum.EnumMeta):
def __contains__(cls, item):
return item in cls.__members__.values()
class MyEnum(str, enum.Enum, metaclass=MyEnumMeta):
FOO = "foo"
BAR = "bar"
Run Code Online (Sandbox Code Playgroud)
编辑:又一个版本,技术上最正确的一个:
import enum
class MyEnumMeta(enum.EnumMeta):
def __contains__(cls, item):
try:
cls(item)
except ValueError:
return False
else:
return True
class MyEnum(enum.Enum, metaclass=MyEnumMeta):
FOO = "foo"
BAR = "bar"
Run Code Online (Sandbox Code Playgroud)
Fin*_*sse 19
如果枚举有许多成员,这种方法可能会更快,因为它不会创建新列表,并且在找到给定值时停止遍历枚举:
any(x.value == 5 for x in Fruit) # True
any(x.value == 7 for x in Fruit) # False
Run Code Online (Sandbox Code Playgroud)
Red*_*chi 16
您可以使用Enum.__members__
- 将名称映射到成员的有序字典:
In [12]: 'Apple' in Fruit.__members__
Out[12]: True
In [13]: 'Grape' in Fruit.__members__
Out[13]: False
Run Code Online (Sandbox Code Playgroud)
Ray*_*emi 13
我只是将 IntEnum 转换为列表并正常测试它:
from enum import IntEnum
class Foo(IntEnum):
ONE = 1
TWO = 2
THREE = 3
print(1 in list(Foo))
True
print(4 in list(Foo))
False
Run Code Online (Sandbox Code Playgroud)
建立在 Reda Maachi 开始的基础上:
6 in Fruit.__members__.values()
Run Code Online (Sandbox Code Playgroud)
返回真
7 in Fruit.__members__.values()
Run Code Online (Sandbox Code Playgroud)
返回假
本来,不要。
\n如果您使用 Enum,则可以使用以下命令测试枚举
\n if isinstance(key, Fruit):\n
Run Code Online (Sandbox Code Playgroud)\n但除此之外, try.. 是测试枚举的 Python 方式。事实上,对于鸭子类型范式的任何突破。
\n测试 IntEnum 中 int 的正确且 Python 的方法是尝试一下,如果失败则捕获 ValueError。
\n上面提出的许多解决方案已被积极弃用,并将在 3.8 中被禁止(“DeprecationWarning:在包含检查中使用非枚举将在 Python 3.8 中引发 TypeError”)
\n从 Python 3.8 \xe2\x80\x93 将其强制转换为列表。
\n在 3.8 左右之后,您可以通过将枚举强制转换为列表来进行测试,如下所示(使用 IntEnum)
\nfrom enum import IntEnum\nclass Fruit(IntEnum):\n Kiwi = 2\n Apple = 4\n Orange = 5\n Pear = 6\n\nfor x in range(8):\n print(f\'{x}, {x in list(Fruit)}\')\n\n
Run Code Online (Sandbox Code Playgroud)\n将打印如下
\n if isinstance(key, Fruit):\n
Run Code Online (Sandbox Code Playgroud)\n
EAFP版本的答案:
try:
Fruit(val)
return True
except ValueError:
return False
Run Code Online (Sandbox Code Playgroud)
您可以使用__members__
特殊属性来迭代成员:
from enum import Enum
class Fruit(Enum):
Apple = 4
Orange = 5
Pear = 6
@staticmethod
def has_value(item):
return item in [v.value for v in Fruit.__members__.values()]
Run Code Online (Sandbox Code Playgroud)