본문 바로가기
Python

[Python] Enumeration

by llHoYall 2023. 2. 21.

이번에는 Python에서 enum 사용법에 대해 살펴보겠습니다.

당연히 포스팅 했던 내용인줄 알았는데, 없어서 찐당황했네요. ㅋ

Fundamental

먼저 기본 사용법을 살펴보겠습니다.

from enum import Enum

# class syntax
class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

# functional syntax
Color = Enum('Color', ['RED', 'GREEN', 'BLUE'])

각각 클래스 문법과 함수형 문법입니다.

값을 정의한 범위로 제한할 수 있어 예상치 못한 오류를 예방할 수 있습니다.

IntEnum & StrEnum

from enum import IntEnum, StrEnum

class Numbers(IntEnum):
    ONE = 1
    TWO = 2
    THREE = 3

class Alphas(StrEnum):
    ALPHA = 'a'
    BETA = 'b'
    GAMMA = 'r'

num = Numbers.ONE
print(num + 1)  # 2

alpha = Alphas.BETA
print(alpha + '!')  # b!

IntEnumStrEnum은 값을 각각 숫자와 문자로 사용할 수 있습니다.

따라서, 예제에서 보시는 바와 같이 기본 형태와 달리 값 자체를 사용할 수 있습니다.

단, StrEnum은 3.11 이후 버전에서만 사용하실 수 있습니다.

개인적으로는 따로 쓸 일은 없었습니다. 기본 형태로도 굳이 하려면 할 수 있기도 하고요.

from enum import Enum

class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

color = Color.RED
print(color.value + 1)  # 2
print(color.name + '!')  # RED!

Flag

C/C++ 등의 언어 사용자들에겐 익숙한 일인 flag도 지원을 합니다.

이게 어떤 의미냐면, 주로 자원이 부족한 임베디드 환경에서 흔히 사용되는데, 각 비트 별로 특정한 의미를 가지는 flag로 설정하여 해당 flag에 의해 프로그램의 흐름이 제어되게 합니다.

from enum import Flag

class Color(Flag):
    RED = 1    # 0001
    GREEN = 2  # 0010
    BLUE = 4   # 0100

purple = Color.RED | Color.BLUE  # 0101

예제를 보시면 쉽게 이해되실 거에요.

auto()

auto()를 사용하면 값을 자동으로 알아서 할당해 주어 더욱 편한 사용이 가능해집니다.

from enum import Enum, Flag, auto

class Color(Enum):
    RED = auto()    # 1
    GREEN = auto()  # 2
    BLUE = auto()   # 3

class InterruptFlag(Flag):
    FLAG1 = auto()  # 1
    FLAG2 = auto()  # 2
    FLAG3 = auto()  # 4

보시다시피 주어진 상황에 맞게 알아서 적절한 값을 넣어줍니다. 이것은 IntEnum이나 StrEnum의 경우에도 마찬가지입니다.

따라서, 특정한 값이 반드시 할당되어야 하는 경우를 제외하면, auto()를 쓰는 편이 더 효율적일 것입니다.

EnumCheck & FlagBoundary

마지막으로 오류를 검출하기 위한 몇 가지 유용한 decorator 및 유용한 기능들을 소개시켜 드리겠습니다.

이 기능들도 3.11에서 추가가 되었기 때문에 버전에 주의해서 사용해주세요.

 

from enum import Enum, Flag, verify, UNIQUE, CONTINUOUS, NAMED_FLAGS

@verify(UNIQUE)
class Color1(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3
    CRIMSON = 1  # ValueError

@verify(CONTINUOUS)
class Color2(Enum):
    RED = 1
    GREEN = 2
    BLUE = 5  # ValueError

@verify(NAMED_FLAGS)
class Color3(Flag):
    RED = 1
    GREEN = 2
    BLUE = 4
    WHITE = 15  # ValueError

먼저, UNIQUE는 유일한 값을 보장해야합니다. 따라서, 이미 있는 값이 중복 정의된 CRIMSON의 경우 에러를 발생시킵니다.

다음으로, CONTINUOUS는 값이 연속됨을 보장해야합니다. 따라서, 3, 4를 건너뛰었기 때문에 에러가 발생됩니다.

마지막으로, NAMED_FLAGS는 정의된 값들이 named flag만 포함해야 합니다.

예제를 보시면, WHITE의 경우인 15(1111b)를 만족시키려면 8에 해당하는 named flag도 존재해야 하지만 빠져있으므로 해당 값들 만으로는 WHITE를 만족시킬 수 없으므로 에러가 발생됩니다.

대부분의 경우 auto()를 사용하면 발생하지 않을 문제들입니다.

따라서, 임의로 정의할 경우에 자동으로 오류를 검출하기 위해 사용됩니다.

 

다음은 잘못된 값이 들어왔을 경우의 처리에 대해 살펴보겠습니다.

from enum import Flag, auto, STRICT, CONFORM, EJECT, KEEP

class StrictFlag(Flag, boundary=STRICT):
    RED = auto()
    GREEN = auto()
    BLUE = auto()

StrictFlag(8)  # ValueError

class ConformFlag(Flag, boundary=CONFORM):
    RED = auto()
    GREEN = auto()
    BLUE = auto()

ConformFlag(9)  # ConformFlag.RED

class EjectFlag(Flag, boundary=EJECT):
    RED = auto()
    GREEN = auto()
    BLUE = auto()

EjectFlag(8)  # 8

class KeepFlag(Flag, boundary=KEEP):
    RED = auto()
    GREEN = auto()
    BLUE = auto()

KeepFlag(9)  # KeepFlag.RED | 8

STRICT의 경우, ValueError를 발생시킵니다.

CONFORM의 경우, 유효한 값만 사용되고 나머지 값은 제거됩니다.

EJECT의 경우, Flag 속성을 잃어버리고 int 값으로 변환됩니다.

KEEP의 경우, 유효한 값만 사용되고 나머지값은 보존됩니다.

필요에 따라 적절히 사용하시면 좋을 것 같아요.

Wrap Up

이번 포스팅에서는 enum에 대해 기본적으로 알면 좋을 내용들을 추려서 정리해보았습니다.

도움이 되셨기를 바랍니다. ^^

'Python' 카테고리의 다른 글

[Python] Create and Draw Graph  (0) 2023.03.01
[Python] Abstract Base Classes  (0) 2023.02.23
[Python] Data Classes  (0) 2023.02.20
[Python] customtkinter 사용하기  (0) 2023.01.17
[PyQt6] GroupBox, CheckBox, RadioButton in QML  (0) 2022.11.21

댓글