如何在不使用try/catch的情况下测试Python枚举中是否存在int值?
使用PythonEnum类,有没有一种方法可以在不使用try/catch的情况下测试Enum是否包含特定的int值 在下列班级:如何在不使用try/catch的情况下测试Python枚举中是否存在int值?,python,enums,Python,Enums,使用PythonEnum类,有没有一种方法可以在不使用try/catch的情况下测试Enum是否包含特定的int值 在下列班级: from enum import Enum class Fruit(Enum): Apple = 4 Orange = 5 Pear = 6 如何测试值6(返回true)或值7(返回false)?您可以使用Enum.\uuuu成员\uuuu-: 测试值 变式1 请注意,Enum有一个名为\u value2member\u map\u的成员(
from enum import Enum
class Fruit(Enum):
Apple = 4
Orange = 5
Pear = 6
如何测试值6(返回true)或值7(返回false)?您可以使用
Enum.\uuuu成员\uuuu
-:
测试值
变式1
请注意,
Enum
有一个名为\u value2member\u map\u
的成员(该成员未记录,在未来的python版本中可能会更改/删除):
变式2
如果您不想依赖此功能,这是另一种选择:
values = [item.value for item in Fruit] # [4, 5, 6]
或者(可能更好):使用集合
;中的操作符将更高效:
values = set(item.value for item in Fruit) # {4, 5, 6}
然后用
5 in values # True
7 in values # False
将has_value
添加到您的类中
然后,您可以将其作为方法添加到类中:
class Fruit(Enum):
Apple = 4
Orange = 5
Pear = 6
@classmethod
def has_value(cls, value):
return value in cls._value2member_map_
print(Fruit.has_value(5)) # True
print(Fruit.has_value(7)) # False
钥匙测试
如果您想测试名称(而不是值),我将使用\u member\u names\u
:
'Apple' in Fruit._member_names_ # True
'Mango' in Fruit._member_names_ # False
只需检查它是否在Enum中_值2成员映射
In[15]: Fruit._value2member_map_
Out[15]: {4: <Fruit.Apple: 4>, 5: <Fruit.Orange: 5>, 6: <Fruit.Pear: 6>}
In[16]: 6 in Fruit._value2member_map_
Out[16]: True
In[17]: 7 in Fruit._value2member_map_
Out[17]: False
[15]中的:水果。_值2成员地图_
Out[15]:{4:,5:,6:}
在[16]中:6在水果中。_值2成员地图_
Out[16]:对
在[17]中:7在水果中。_值2成员地图_
Out[17]:假
建立在Reda Maachi的基础上:
6 in Fruit.__members__.values()
返回True
7 in Fruit.__members__.values()
返回False(假)不返回。
如果您使用的是Enum,则可以使用
if isinstance(key, Fruit):
但如果不是这样的话,试试。。是测试枚举的Python方法。事实上,对于鸭子打字范式的任何突破
测试IntEnum中的int的正确的、类似python的方法是尝试一下,并在出现故障时捕获ValueError
上面提出的许多解决方案都已被弃用,并将被3.8禁止(“弃用警告:在包含检查中使用非枚举将在Python 3.8中引发TypeError”)
如果您真的对保持代码的现代感兴趣,那么您可以使用
if key in Fruit:
答案的一个版本:
试试看:
水果(val)
返回真值
除值错误外:
返回错误
您可以使用来迭代成员:
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()]
还有另一个一行解决方案,但还没有人提到:
is_value_in_fruit = any(f.value == value_to_check for f in Fruit)
此外,如果您使用IntEnum
而不是Enum
,(class-Fruit(IntEnum)
)您可以这样做
is_value_in_fruit = any(f == value_to_check for f in Fruit)
IntEnum
+成员
您可以使用IntEnum
和\uuuu成员\uuuu
实现所需的行为:
from enum import IntEnum
class Fruit(IntEnum):
Apple = 4
Orange = 5
Pear = 6
>>> 6 in Fruit.__members__.values()
True
>>> 7 in Fruit.__members__.values()
False
Enum
+列表理解+.value
如果您必须/想要坚持使用Enum
,可以执行以下操作:
>>> 6 in [f.value for f in Fruit]
True
>>> 7 in [f.value for f in Fruit]
False
EAPF+值错误
或者你可以使用比许可更容易请求原谅的方法:
有一种方法可以让所有枚举都能够检查项目是否存在:
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"
现在,您可以进行简单的检查:
>>> "foo" in MyEnum
True
如果所有枚举值始终为同一类型(例如字符串),则更简单:
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"
编辑:另一个版本,技术上最正确的版本:
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"
如果枚举有许多成员,这种方法可以更快,因为它不生成新列表,并且在找到给定值时停止遍历枚举:
any(水果中x的x.value==5)#正确
任意(水果中x的x.value==7)#错误
这个怎么样
从枚举导入枚举
水果类(枚举):
苹果=4
橙色=5
梨=6
has_苹果=4英寸[n.水果中的n值]
这样,您还可以执行以下操作:
在[n.水果中n的名称]中有\u apples=“Apple”
我只是将一个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
问题是测试int值,而不是字符串。枚举中是否没有包含这些值的成员?这不是很奇怪吗?这与问题的方向相反。这对价值观不起作用!(用于“键”)回答者可能有Apple=“Apple”
,所以他有相同的字母和字母箱用于键和值。。。如果你有APPLE=“APPLE”
,那么。\uuuuu成员\uuuuuuu
将导致{'APPLE':,'GRAPE':}
我个人更喜欢第二种解决方案。谢谢。这两个建议都不是特别节省记忆或时间,尽管从这些方面来说也不是很重。在我的例子中,我正在使用标准库中的HTTPStatus
enum,该库目前包含57个条目。我永远不会处理枚举中的整个值列表,缓存它们是我希望避免的事情。@无如果您担心速度,您可以为查找创建一个集。这将使用一些额外的内存,但不是很大的内存量…为什么返回值周围有括号?必须使用返回any(value==item.value[0]用于cls中的item)
使用Python3时枚举结构是否发生了更改?\u value2member\u map\u
是未记录的功能,所以最好避免使用它。这看起来是一种非常干净的方式。不幸的是,当我测试这个(至少在Py3.7中)时,它不是那样工作的。export.\uuuu members\uuuuu.values()的计算结果为odict\u值([,]),上面对6和7的测试对我来说都返回False。但这返回true:>>水果中的水果。橙色。_成员_uu.values()true
我想指出,这只适用于IntEnum。这个解决方案实际上是错误的。因为OP询问如何检查值是否在枚举中,例如6或7。这将始终返回false,因为枚举的所有成员实际上都不等于6或7。试试看,这个应该高很多。。。简单有效,谢谢!
>>> "foo" in MyEnum
True
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"
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"
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