如何在不使用 try/catch 的情况下测试 Python Enum 中是否存在 int 值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43634618/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 23:15:40  来源:igfitidea点击:

How do I test if int value exists in Python Enum without using try/catch?

pythonenums

提问by Nathan Kovner

Using the Python Enum class, is there a way to test if an Enum contains a specific int value without using try/catch?

使用 Python Enum 类,有没有办法在不使用 try/catch 的情况下测试 Enum 是否包含特定的 int 值?

With the following class:

使用以下课程:

from enum import Enum

class Fruit(Enum):
    Apple = 4
    Orange = 5
    Pear = 6

How can I test for the value 6 (returning true), or the value 7 (returning false)?

如何测试值 6(返回 true)或值 7(返回 false)?

回答by hiro protagonist

test for values

测试值

variant 1

变体 1

note that an Enumhas a member called _value2member_map_(which is undocumented and may be changed/removed in future python versions):

请注意, anEnum有一个名为的成员_value2member_map_(未记录在案,可能会在未来的 Python 版本中更改/删除):

print(Fruit._value2member_map_)
# {4: <Fruit.Apple: 4>, 5: <Fruit.Orange: 5>, 6: <Fruit.Pear: 6>}

you can test if a value is in your Enumagainst this map:

你可以测试一个值是否在你的Enum地图中:

5 in Fruit._value2member_map_  # True
7 in Fruit._value2member_map_  # False

variant 2

变体2

if you do not want to rely on this feature this is an alternative:

如果您不想依赖此功能,这是一种替代方法:

values = [item.value for item in Fruit]  # [4, 5, 6]

or (probably better): use a set; the inoperator will be more efficient:

或(可能更好):使用set; 该in运营商将更加有效:

values = set(item.value for item in Fruit)  # {4, 5, 6}

then test with

然后用

5 in values  # True
7 in values  # False

add has_valueto your class

添加has_value到您的班级

you could then add this as a method to your class:

然后,您可以将其作为方法添加到您的类中:

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

test for keys

测试钥匙

if you want to test for the names (and not the values) i would use _member_names_:

如果你想测试名称(而不是值),我会使用_member_names_

'Apple' in Fruit._member_names_  # True
'Mango' in Fruit._member_names_  # False

回答by Reda Maachi

You could use Enum.__members__- an ordered dictionary mapping names to members:

您可以使用Enum.__members__-将名称映射到成员的有序字典

In [12]: 'Apple' in Fruit.__members__
Out[12]: True

In [13]: 'Grape' in Fruit.__members__
Out[13]: False

回答by manu3d

Building on what Reda Maachi started:

建立在 Reda Maachi 开始的基础上:

6 in Fruit.__members__.values() 

returns True

返回真

7 in Fruit.__members__.values()  

returns False

返回假

回答by JianWei

Just check whether it's in Enum. _value2member_map_

只需检查它是否在 Enum. _value2member_map_

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

回答by Alex Jolig

You could use __members__special attributeto iterate over members:

您可以使用__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 Connection.__members__.values()]

回答by Joshua Ryan

There's another one liner solution nobody has mentioned yet:

还有另一种没有人提到的单线解决方案:

is_value_in_fruit = any(f.value == value_to_check for f in Fruit)

Also, if you use IntEnuminstead of Enum, (class Fruit(IntEnum)) you can just do this

此外,如果您使用IntEnum代替Enum, ( class Fruit(IntEnum)) 您可以这样做

is_value_in_fruit = any(f == value_to_check for f in Fruit) 

回答by maciek

IntEnum+ __members__

IntEnum+ __members__

You could use IntEnumand __members__to achieve required behaviour:

您可以使用IntEnum__members__来实现所需的行为:

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+ list comprehension + .value

Enum+ 列表理解 + .value

If you must/want stick to Enum, you can do:

如果你必须/想要坚持Enum,你可以这样做:

>>> 6 in [f.value for f in Fruit]
True
>>> 7 in [f.value for f in Fruit]
False

EAPF + ValueError

EAPF + ValueError

Or you can use easier to ask for forgiveness than permissionmethod:

或者你可以使用比许可更容易请求原谅的方法:

try:
    Fruit(x)
except ValueError:
    return False
else:
    return True

回答by Konchog

Don't.

别。

If you are using Enum, you can test for enum with

如果您使用的是枚举,则可以使用

     if isinstance(key, Fruit):

But otherwise, try.. is the pythonic way to test for enum. Indeed, for any break in the duck-typing paradigm.

但除此之外, try.. 是测试枚举的 Pythonic 方式。事实上,对于鸭子类型范式的任何突破。

The correct, and pythonic, way of testing for an int in an IntEnum is to give it a go and to catch a ValueError if there's a failure.

在 IntEnum 中测试 int 的正确和 Pythonic 方法是试一试并在出现故障时捕获 ValueError。

Many of the solutions proposed above are actively deprecated and will be disallowed by 3.8 ( "DeprecationWarning: using non-Enums in containment checks will raise TypeError in Python 3.8" )

上面提出的许多解决方案都被积极弃用,将被 3.8 禁止(“DeprecationWarning:在包含检查中使用非枚举将引发 Python 3.8 中的 TypeError”)

If you are really disinterested in keeping your code modern, then you can just use

如果你真的不想让你的代码保持现代,那么你可以使用

if key in Fruit:

回答by ComeOnGetMe

An EAFPversion of the answer:

答案的EAFP版本:

try: 
    Fruit(val)
    return True
except ValueError:
    return False