Enum

Enum

  • enumeration : 열거형
  • 고유한 상숫값에 연결된 기호 이름(멤버)의 집합
  • 열거형은 이터레이트(반복)될 수 있다.

Enum 의 사용과 구성

1
2
3
4
5
6
7
8
9
10
11
from enum import Enum

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

class CommitType(Enum):
    UPDATE = 'update something'
    FIX = 'fix bug'
    DELETE = 'delete something'
  • enum 모듈의 Enum 클래스를 이용한다.
  • Enum 클래스를 상속받아 자식 클래스를 만든다.(Color 클래스와 같이)
  • Enum 은 멤버 들을 가질 수 있다.
  • 멤버이름(name)상숫값(value) 쌍으로 이루어진다.
  • 위 예시에서 이름은 RED, GREEN, BLUE, UPDATE … 등에 해당되며, UPPER_CASE 로 작성하는 것을 권장한다.
  • 상숫값은 1, 2, 3, update_something … 등에 해당되며 아무 값이나될 수 있다. (int, str …)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from enum import Enum

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

print(Color.RED)
>> Color.RED

print(Color.RED.name)
>> RED

print(Color.RED.value)
>> 1
  • <EnumClass>.<member name> 를 통해 멤버에 접근할 수 있다.
  • <EnumClass>.<member name>.name 를 통해 멤버의 “이름”을 반환받을 수 있다.
  • <EnumClass>.<member name>.value 를 통해 멤버의 “상숫값”을 반환받을 수 있다.

Enum 을 사용하는 이유

가독성 및 명확성

상숫값으로 필요한 어떤 값을 magic number나 의미 없는 문자열을 이용하는 대신, 의미 있는 이름을 가진 열거형 멤버를 사용해 코드의 의도를 직관적으로 파악할 수 있도록 함.

1
2
3
# enum 을 사용하지 않을 경우
if status == 1:    # --> 1이 무엇을 의미하는지 알 수 없음
    breakpoint()
1
2
3
4
5
6
7
8
# enum 을 사용할 경우
class StatusCode(Enum):
    SUCCESS = 0
    FAIL = 1
    PENDING = 2

if status == StatusCode.FAIL.value:    # --> 실패를 뜻함을 쉽게 알 수 있음
    breakpoint()

타입 안정성 강화

enum 은 특정 값들만을 사용하도록 제한하여, 예상치 못한 잘못된 값이 쓰이는 것을 방지할 수 있습니다. 이를 통해 런타임 오류를 줄여줍니다.

1
2
3
4
5
6
7
8
9
10
11
# enum 을 사용하지 않을 경우

status = 4

if status == 0:
    ...
elif status == 1:
    ...
elif status == 2:
    ...
# --> 어떠한 분기에도 해당되지 않음. 개발자의 의도에 벗어나는 런타임 오류를 발생시킬 수 있음.

유지보수 용이성과 코드 재사용성

특정 상수값이 전역적으로 변경되어야 할 경우, enum 정의 부분만 변경해줌으로써 전체 코드에 일괄적으로 적용할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
# enum 을 사용하지 않을 경우
if status == 0:
    print("성공했습니다.")

...

if status == 0:
    status += 200

# --> status code 체계를 변경할 경우, 모든 부분에서 0, 1, 2 ... 와 같은 값을 변경해줘야 함.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# enum 을 사용할 경우  
class StatusCode(Enum):
    SUCCESS = 200 # 0 -> 200
    FAIL = 400    # 1 -> 400
    PENDING = 500 # 2 -> 500

if status == StatusCode.SUCCESS.value:
    print("성공했습니다.")

...

if status == StatusCode.SUCCESS.value:
    status += 200

# --> status code 체계가 변경되어도 enum 정의 부분에서만 수정해주면 됨.

Enum 사용하기

Enum 모듈 내용 살펴보기

모듈 내용 설명
class enum.Enum 열거형 상수를 만들기 위한 베이스 클래스
class enum.IntEnum int 의 서브 클래스이기도 한 열거형 상수를 만들기 위한 베이스 클래스
class enum.IntFlag IntFlag 멤버십을 잃지 않고 비트 연산자를 사용하여 결합할 수 있는 열거형 상수를 만들기 위한 베이스 클래스.
class enum.Flag Flag 멤버십을 잃지 않고 비트 연산을 사용하여 결합할 수 있는 열거형 상수를 만들기 위한 베이스 클래스.
enum.unique() 한 값에 하나의 이름 만 연결되도록 하는 Enum 클래스 데코레이터.
class enum.auto 인스턴스는 Enum 멤버에 적절한 값으로 바뀐다. 기본적으로, 초깃값은 1부터 시작.

Enum 으로 선언된 열거형 상수들에 대한 정보 얻기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from enum import Enum

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

print(Color.RED)
>> Color.RED

print(Color.RED.name)
>> RED

print(Color.RED.value)
>> 1

print(repr(Color.RED))
>> <Color.RED: 1>

print(type(Color.RED))
>> <enum 'Color'>

print(Color(1))
>> <Color.RED: 1>

이터레이션

  • Enum 은 정의된 순서대로 이터레이션이 가능하다.
1
2
3
4
5
6
7
8
9
10
11
class Color(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

for color in Color:
    print(color)

>> Color.RED
>> Color.GREEN
>> Color.BLUE

딕셔너리와 집합에서 사용

  • Enum 은 해시 가능하므로 딕셔너리와 집합에서 사용 가능
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from enum import Enum

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

colors = {}
colors[Color.RED] = 'red'
colors[Color.GREEN] = 'green'

if colors == {Color.RED:'red', Color.GREEN:'green'}:
    print('Color는 해시가 가능합니다.')

>> Color는 해시가 가능합니다.

auto 자동 값 사용하기

  • value 가 중요하지 않을 경우, auto 를 사용해 자동으로 값이 할당되도록 할 수 있음
1
2
3
4
5
6
7
8
9
from enum import Enum, auto

class Color(Enum):
    RED = auto()
    GREEN = auto()
    BLUE = auto()

list(Color)
>> [<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 3>]

비교

  • Enum 은 값이 아닌 아이덴티티로 비교할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from enum import Enum, auto

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

if Color.RED is Color.RED:
    print('RED is RED')

if Color.RED == Color.RED:
    print('RED == RED')

if Color.RED is 1:
    print('RED is 1')

if Color.RED == 1:
    print('RED == 1')

>> RED is RED
>> RED == RED

아직 살펴보지 않은 부분

  • IntFlag
  • Flag

Reference

https://docs.python.org/ko/3.9/library/enum.html

Comments