programing

try/catch를 사용하지 않고 Python Enum에 int 값이 있는지 테스트하려면 어떻게 해야 합니까?

sourcejob 2023. 7. 18. 21:41
반응형

try/catch를 사용하지 않고 Python Enum에 int 값이 있는지 테스트하려면 어떻게 해야 합니까?

Python Enum 클래스를 사용하여 try/catch를 사용하지 않고 Enum에 특정 int 값이 포함되어 있는지 테스트할 수 있는 방법이 있습니까?

다음 클래스와 함께:

from enum import Enum

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

값 6(참 반환) 또는 값 7(거짓 반환)을 테스트하려면 어떻게 해야 합니까?

값 검정

변종 1

로 삼다Enum라는 멤버가 있습니다._value2member_map_(문서화되지 않았으며 향후 파이썬 버전에서 변경/수정될 수 있음):

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

당신은 당신의 안에 값이 있는지 테스트할 수 있습니다.Enum지도에 설명합니다.

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

변종 2

이 기능을 사용하지 않으려면 이 방법을 사용할 수 있습니다.

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

더 나은 편 (으)로: 용사합다니편을 합니다.set그자리의 in연산자가 더 효율적일 것입니다.

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

python 3.9 (?) python 오퍼에서 시작하여 다음을 수행할 수 있습니다.

from enum import IntEnum

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

print(6 in iter(Fruit))  # True

로 " 을음생필없습다니요가할성"를 .list되풀이하여.iter(Fruit)그러면 됩니다. 반복적으로 필요한 경우 위와 같이 집합을 생성할 가치가 있을 수 있습니다.

values = set(Fruit)
print(5 in values)  # True

키 테스트

이 아닌) , 는 만약당값이신테이싶것다나입니사다용할는름고면하아를 사용할 입니다._member_names_:

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

모든 열거형이 항목이 있는지 확인할 수 있도록 하는 방법이 있습니다.

import enum 

class MyEnumMeta(enum.EnumMeta): 
    def __contains__(cls, item): 
        return isinstance(item, cls) or 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"

편집: @MestreLion의 코멘트에 따라, 저는 첫 번째 예를 포함하도록 업데이트했습니다.isinstance확인합니다. 확인하지 않으면 이미 인스턴스화된 열거형 값을 확인하는 경우 테스트가 실패합니다.

편집: 또 다른 버전, 기술적으로 가장 정확한 버전:

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"

사용할 수 있습니다.Enum.__members__이름을 멤버에 매핑하는 순서 사전:

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

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

열거형에 구성원이 많은 경우 새 목록을 만들지 않고 지정된 값이 발견될 때 열거형 보행을 중지하므로 이 접근 방식이 더 빠를 수 있습니다.

any(x.value == 5 for x in Fruit)  # True
any(x.value == 7 for x in Fruit)  # False

Reda Maachi가 시작한 것을 기반으로 합니다.

6 in Fruit.__members__.values() 

True를 반환합니다.

7 in Fruit.__members__.values()  

False를 반환합니다.

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

특수 속성을 사용하여 멤버 위에 반복할 수 있습니다.

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()]

원래는 하지 마.

Enum을 사용하는 경우 다음을 사용하여 Enum을 테스트할 수 있습니다.

     if isinstance(key, Fruit):

하지만 그렇지 않다면, 시도해 보세요.열거형을 테스트하는 파이썬적인 방법입니다.사실, 오리 유형화 패러다임의 어떤 휴식에도 불구하고.

IntEnum에서 int를 테스트하는 정확하고 피톤적인 방법은 시도해보고 실패했을 때 ValueError를 잡는 것입니다.

위에서 제안된 솔루션 중 많은 수가 적극적으로 사용되지 않으며 3.8에서 허용되지 않습니다("DecrecationWarning: 격납 검사에서 열거형이 아닌 것을 사용하면 Python 3.8에서 TypeError가 발생합니다").

Python 3.8에서 – 목록에 강제로 포함시킵니다.

3.8 정도 이후에는 다음과 같이 열거형을 강제로 목록에 넣어 테스트할 수 있습니다(IntEnum 사용).

from enum import IntEnum
class Fruit(IntEnum):
     Kiwi = 2
     Apple = 4
     Orange = 5
     Pear = 6

for x in range(8):
     print(f'{x}, {x in list(Fruit)}')

다음과 같이 인쇄됩니다.

0, False
1, False
2, True
3, False
4, True
5, True
6, True
7, False

안에 있는지만 확인하세요.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

EAFP 버전의 답변:

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

아직 아무도 언급하지 않은 라이너 솔루션이 하나 더 있습니다.

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) 

이건 어때?

from enum import Enum

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

has_apples = 4 in [n.value for n in Fruit]

이렇게 하면 다음 작업도 수행할 수 있습니다.

has_apples = "Apple" in [n.name for n in Fruit]

IntEnum+__members__

사용할 수 있습니다.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목록 이해 +.value

계속해야 하는 경우Enum할 수 있는 일:

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

EAPF +ValueError

또는 허가 방법보다 용서를 구하기 쉬운 방법을 사용할 수 있습니다.

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

이를 위한 가장 깨끗하고 친숙한 방법은try/except:

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

# If you want it in function form
def is_fruit(x):
    try:
        Fruit(x)
    except ValueError:
        return False
    else:
        return True
class MyEnumMixin:

    raw_values = None  # for IDE autocomplete

    def __new__(cls, value):
        if 'raw_values' not in cls.__dict__:
            cls.raw_values = set()
        cls.raw_values.add(value)
        if cls.__bases__[0] is MyEnumMixin:
            member = object().__new__(cls)
        else:
            member = super().__new__(cls, value)
        member._value_ = value
        return member



class MyEnum(MyEnumMixin, Enum):
    FOO = 1
    BAR = 'bar'

print(1 in MyEnum.raw_values)
print('bar' in MyEnum.raw_values)



class MyStrEnumMixin(MyEnumMixin, str):
    pass

class MyStrEnum(MyStrEnumMixin, Enum):
    FOO = 'foo'
    BAR = 'bar'

print('foo' in MyStrEnum.raw_values)
print('bar' in MyStrEnum.raw_values)

언급URL : https://stackoverflow.com/questions/43634618/how-do-i-test-if-int-value-exists-in-python-enum-without-using-try-catch

반응형