enum — 열거형 지원
enum — 열거형 지원
버전 3.4에 추가됨.
이 페이지는 API 참조 정보를 담고 있어요. 튜토리얼 정보와 더 고급 주제 논의는 기본 튜토리얼, 고급 튜토리얼, Enum Cookbook을 참고하세요.
출처: Python 표준 라이브러리
본문
열거형(enumeration)은:
- 고유한 값에 바인딩된 상징적 이름(멤버)들의 집합
- 정의 순서대로 표준(즉, 별칭이 아닌) 멤버를 돌려주도록 반복할 수 있음
- 호출 문법으로 값별로 멤버를 돌려줌
- 인덱스 문법으로 이름별로 멤버를 돌려줌
열거형은 클래스 문법 또는 함수 호출 문법으로 만들 수 있어요.
>>> from enum import Enum
>>> # class syntax
>>> class Color(Enum):
... RED = 1
... GREEN = 2
... BLUE = 3
>>> # functional syntax
>>> Color = Enum('Color', [('RED', 1), ('GREEN', 2), ('BLUE', 3)])
클래스 문법으로 Enum을 만들 수 있어도, Enum은 일반 Python 클래스가 아니에요. Enum이 일반 클래스와 어떻게 다른지는 상세한 내용을 참고하세요.
용어 — 클래스
Color는 열거형(enumeration, 또는 enum)이에요. 속성Color.RED,Color.GREEN등은 열거형 멤버(멤버)이고 기능적으로 상수예요. 열거형 멤버는 이름과 값을 가져요(Color.RED의 이름은RED,Color.BLUE의 값은3등).
모듈 내용
| 이름 | 설명 |
|---|---|
EnumType |
Enum과 그 하위 클래스의 타입. |
Enum |
열거형 상수를 만들기 위한 기본 클래스. |
IntEnum |
int의 하위 클래스이기도 한 열거형 상수를 만들기 위한 기본 클래스. |
StrEnum |
str의 하위 클래스이기도 한 열거형 상수를 만들기 위한 기본 클래스. |
Flag |
비트 연산으로 결합해도 Flag 멤버십을 잃지 않는 열거형 상수를 만들기 위한 기본 클래스. |
IntFlag |
비트 연산자로 결합해도 IntFlag 멤버십을 잃지 않는 열거형 상수를 만들기 위한 기본 클래스. IntFlag 멤버는 int의 하위 클래스이기도 함. |
ReprEnum |
혼합된 타입의 str()을 유지하기 위해 IntEnum, StrEnum, IntFlag가 사용함. |
EnumCheck |
verify()와 함께 사용해 주어진 열거형이 다양한 제약을 만족하는지 보장하는 값 CONTINUOUS, NAMED_FLAGS, UNIQUE를 가진 열거형. |
FlagBoundary |
열거형에서 잘못된 값을 어떻게 다루는지 더 세밀하게 제어할 수 있게 하는 값 STRICT, CONFORM, EJECT, KEEP을 가진 열거형. |
EnumDict |
EnumType을 서브클래싱할 때 사용하는 dict의 하위 클래스. |
auto |
Enum 멤버에 대해 적절한 값으로 대체되는 인스턴스. StrEnum은 멤버 이름의 소문자 버전을 기본으로 하고, 다른 Enum은 기본적으로 1부터 증가. |
@enum.property |
멤버 이름과 충돌하지 않으면서 Enum 멤버가 속성을 가질 수 있게 함. value와 name 속성이 이런 식으로 구현됨. |
@unique |
어떤 값에도 오직 하나의 이름만 바인딩되도록 보장하는 Enum 클래스 데코레이터. |
@verify |
열거형에 대해 사용자가 선택한 제약을 검사하는 Enum 클래스 데코레이터. |
@member |
obj를 멤버로 만듦. 데코레이터로 쓸 수 있음. |
@nonmember |
obj를 멤버로 만들지 않음. 데코레이터로 쓸 수 있음. |
@global_enum |
enum의 str()과 repr()을 멤버가 클래스가 아니라 모듈에 속한 것처럼 표시하도록 수정하고, enum 멤버를 전역 네임스페이스로 내보냄. |
show_flag_values() |
플래그에 포함된 모든 2의 거듭제곱 정수 리스트를 돌려줌. |
enum.bin() |
내장 bin()과 같지만, 음수 값은 2의 보수로 표현되고 선두 비트가 항상 부호를 나타냄(0은 양수, 1은 음수). |
버전 3.6에 추가됨: Flag, IntFlag, auto
버전 3.11에 추가됨: StrEnum, EnumCheck, ReprEnum, FlagBoundary, property, member, nonmember, global_enum, show_flag_values
버전 3.13에 추가됨: EnumDict
데이터 타입
class enum.EnumType
EnumType은 enum 열거형의 메타클래스예요. EnumType을 서브클래싱할 수 있어요 — 자세한 내용은 EnumType 서브클래싱을 참고하세요.
EnumType은 최종 enum에 올바른 __repr__(), __str__(), __format__(), __reduce__() 메서드를 설정하고, enum 멤버를 만들고, 중복을 적절히 처리하고, enum 클래스에 대한 반복을 제공하는 등의 역할을 담당해요.
버전 3.11에 추가됨: 3.11 이전에 EnumType은 EnumMeta라고 불렸으며, 여전히 별칭으로 사용 가능함.
call(cls, value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)
이 메서드는 두 가지 방식으로 호출돼요.
기존 멤버 조회 — cls: 호출되는 enum 클래스, value: 조회할 값.
기존 enum이 멤버가 없다면, cls enum을 사용해 새 enum 만들기 — cls: 호출되는 enum 클래스, value: 만들 새 Enum의 이름, names: 새 Enum 멤버의 이름/값, module: 새 Enum이 만들어지는 모듈 이름, qualname: 모듈 안에서 이 Enum을 찾을 수 있는 실제 위치, type: 새 Enum용 믹스인 타입, start: Enum의 첫 정수 값(auto가 사용), boundary: 비트 연산의 범위 밖 값 처리 방법(Flag만).
contains(cls, member)
member가 cls에 속하면 True를 돌려줘요.
>>> some_var = Color.RED
>>> some_var in Color
True
>>> Color.RED.value in Color
True
버전 3.12에서 변경: Python 3.12 이전에는 포함 검사에 비-Enum 멤버가 쓰이면 TypeError가 발생했음.
dir(cls)
['__class__', '__doc__', '__members__', '__module__']와 cls의 멤버 이름들을 돌려줘요.
>>> dir(Color)
['BLUE', 'GREEN', 'RED', '__class__', '__contains__', '__doc__', '__getitem__', '__init_subclass__', '__iter__', '__len__', '__members__', '__module__', '__name__', '__qualname__']
getitem(cls, name)
cls에서 name과 일치하는 Enum 멤버를 돌려주거나, KeyError를 발생시켜요.
>>> Color['BLUE']
<Color.BLUE: 3>
iter(cls)
cls의 각 멤버를 정의 순서대로 돌려줘요.
>>> list(Color)
[<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 3>]
len(cls)
cls의 멤버 수를 돌려줘요.
>>> len(Color)
3
members
모든 enum 이름을 그 멤버로 매핑하는 매핑을 돌려줘요(별칭 포함).
reversed(cls)
cls의 각 멤버를 역순 정의 순서로 돌려줘요.
>>> list(reversed(Color))
[<Color.BLUE: 3>, <Color.GREEN: 2>, <Color.RED: 1>]
class enum.Enum
Enum은 모든 enum 열거형의 기본 클래스예요.
name
Enum 멤버를 정의하는 데 사용된 이름.
>>> Color.BLUE.name
'BLUE'
value
Enum 멤버에게 주어진 값.
>>> Color.RED.value
1
멤버의 값이며, __new__()에서 설정할 수 있어요.
Enum 멤버 값 — 멤버 값은 무엇이든 될 수 있어요:
int,str등. 정확한 값이 중요하지 않으면auto인스턴스를 쓸 수 있고 적절한 값이 선택돼요. 자세한 내용은auto를 참고하세요.dict,list, 가변 dataclass 같은 가변/비해시 값도 쓸 수 있지만, 생성 중 enum의 가변/비해시 값 총 수에 상대적인 이차 성능 영향이 있어요.
name
멤버의 이름.
value
멤버의 값. __new__()에서 설정할 수 있어요.
order
더 이상 사용되지 않고, 하위 호환성용으로 유지돼요(클래스 속성, 클래스 생성 중 제거됨).
_order_ 속성은 Python 2와 Python 3 코드를 동기화하는 데 도움이 되도록 제공할 수 있어요. 열거형의 실제 순서와 검사되어, 둘이 일치하지 않으면 오류를 발생시켜요.
>>> class Color(Enum):
... _order_ = 'RED GREEN BLUE'
... RED = 1
... BLUE = 3
... GREEN = 2
...
Traceback (most recent call last):
...
TypeError: member order does not match _order_:
['RED', 'BLUE', 'GREEN']
['RED', 'GREEN', 'BLUE']
참고 — Python 2 코드에서는 정의 순서가 기록되기 전에 손실되므로
_order_속성이 필요해요.
버전 3.6에 추가됨.
ignore
_ignore_는 생성 중에만 사용되고, 생성이 완료되면 열거형에서 제거돼요.
_ignore_는 멤버가 되지 않을 이름들의 목록이고, 그 이름들도 완성된 열거형에서 제거돼요. 예제는 TimePeriod를 참고하세요.
버전 3.7에 추가됨.
dir(self)
['__class__', '__doc__', '__module__', 'name', 'value']와 self.__class__에 정의된 공개 메서드를 돌려줘요.
>>> from enum import Enum
>>> import datetime as dt
>>> class Weekday(Enum):
... MONDAY = 1
... TUESDAY = 2
... WEDNESDAY = 3
... THURSDAY = 4
... FRIDAY = 5
... SATURDAY = 6
... SUNDAY = 7
... @classmethod
... def today(cls):
... print(f'today is {cls(dt.date.today().isoweekday()).name}')
...
>>> dir(Weekday.SATURDAY)
['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'today', 'value']
generate_next_value(name, start, count, last_values)
name— 정의 중인 멤버의 이름(예:'RED').start— Enum의 시작 값. 기본값은 1.count— 이 멤버를 포함하지 않는, 현재 정의된 멤버 수.last_values— 이전 값들의 리스트.
auto가 돌려줄 다음 값을 결정하는 데 사용되는 정적 메서드예요.
참고 — 표준
Enum클래스에서 선택되는 다음 값은 본 최고 값에 1을 더한 값이에요.Flag클래스에서는 다음 값이 다음으로 높은 2의 거듭제곱이 돼요.
이 메서드는 오버라이드할 수 있어요. 예:
>>> from enum import auto, Enum
>>> class PowersOfThree(Enum):
... @staticmethod
... def _generate_next_value_(name, start, count, last_values):
... return 3 ** (count + 1)
... FIRST = auto()
... SECOND = auto()
...
>>> PowersOfThree.SECOND.value
9
버전 3.6에 추가됨. 버전 3.13에서 변경: 이전 버전은 최고 값 대신 마지막으로 본 값을 사용했음.
init(self, *args, **kwds)
기본적으로 아무것도 하지 않아요. 멤버 할당에 여러 값이 주어지면 그 값들이 __init__의 별도 인자가 돼요. 예:
>>> from enum import Enum
>>> class Weekday(Enum):
... MONDAY = 1, 'Mon'
Weekday.__init__()은 Weekday.__init__(self, 1, 'Mon')으로 호출돼요.
init_subclass(cls, **kwds)
후속 하위 클래스를 더 구성하는 데 사용되는 클래스 메서드예요. 기본적으로 아무것도 하지 않아요.
missing(cls, value)
cls에서 찾을 수 없는 값을 조회하는 클래스 메서드예요. 기본적으로 아무것도 하지 않지만, 사용자 정의 검색 동작을 구현하도록 오버라이드할 수 있어요.
>>> from enum import auto, StrEnum
>>> class Build(StrEnum):
... DEBUG = auto()
... OPTIMIZED = auto()
... @classmethod
... def _missing_(cls, value):
... value = value.lower()
... for member in cls:
... if member.value == value:
... return member
... return None
...
>>> Build.DEBUG.value
'debug'
>>> Build('deBUG')
<Build.DEBUG: 'debug'>
버전 3.6에 추가됨.
new(cls, *args, **kwds)
기본적으로 존재하지 않아요. enum 클래스 정의나 믹스인 클래스(예: int)에서 지정하면, 멤버 할당에 주어진 모든 값이 전달돼요. 예:
>>> from enum import Enum
>>> class MyIntEnum(int, Enum):
... TWENTYSIX = '1a', 16
이것은 int('1a', 16) 호출과 멤버 값 26을 만들어요.
참고 — 사용자 정의
__new__를 쓸 때는super().__new__를 사용하지 말고 적절한__new__를 호출하세요.
repr(self)
repr() 호출에 사용되는 문자열을 돌려줘요. 기본적으로 Enum 이름, 멤버 이름, 값을 돌려주지만 오버라이드할 수 있어요.
>>> from enum import auto, Enum
>>> class OtherStyle(Enum):
... ALTERNATE = auto()
... OTHER = auto()
... SOMETHING_ELSE = auto()
... def __repr__(self):
... cls_name = self.__class__.__name__
... return f'{cls_name}.{self.name}'
...
>>> OtherStyle.ALTERNATE, str(OtherStyle.ALTERNATE), f"{OtherStyle.ALTERNATE}"
(OtherStyle.ALTERNATE, 'OtherStyle.ALTERNATE', 'OtherStyle.ALTERNATE')
str(self)
str() 호출에 사용되는 문자열을 돌려줘요. 기본적으로 Enum 이름과 멤버 이름을 돌려주지만 오버라이드할 수 있어요.
>>> from enum import auto, Enum
>>> class OtherStyle(Enum):
... ALTERNATE = auto()
... OTHER = auto()
... SOMETHING_ELSE = auto()
... def __str__(self):
... return f'{self.name}'
...
>>> OtherStyle.ALTERNATE, str(OtherStyle.ALTERNATE), f"{OtherStyle.ALTERNATE}"
(<OtherStyle.ALTERNATE: 1>, 'ALTERNATE', 'ALTERNATE')
format(self)
format()과 f-string 호출에 사용되는 문자열을 돌려줘요. 기본적으로 __str__() 반환 값을 돌려주지만 오버라이드할 수 있어요.
>>> from enum import auto, Enum
>>> class OtherStyle(Enum):
... ALTERNATE = auto()
... OTHER = auto()
... SOMETHING_ELSE = auto()
... def __format__(self, spec):
... return f'{self.name}'
...
>>> OtherStyle.ALTERNATE, str(OtherStyle.ALTERNATE), f"{OtherStyle.ALTERNATE}"
(<OtherStyle.ALTERNATE: 1>, 'OtherStyle.ALTERNATE', 'ALTERNATE')
참고 —
Enum과 함께auto를 쓰면 1부터 시작하는 증가하는 정수 값이 돼요.
버전 3.12에서 변경: Dataclass 지원 추가.
add_alias()
기존 멤버에 새 이름을 별칭으로 추가해요.
>>> Color.RED._add_alias_("ERROR")
>>> Color.ERROR
<Color.RED: 1>
이름이 이미 다른 멤버에 할당돼 있으면 NameError를 발생시켜요.
버전 3.13에 추가됨.
add_value_alias()
기존 멤버에 새 값을 별칭으로 추가해요.
>>> Color.RED._add_value_alias_(42)
>>> Color(42)
<Color.RED: 1>
값이 이미 다른 멤버와 연결돼 있으면 ValueError를 발생시켜요. 예제는 MultiValueEnum을 참고하세요.
버전 3.13에 추가됨.
class enum.IntEnum
IntEnum은 Enum과 같지만, 그 멤버는 정수이기도 하고 정수를 쓸 수 있는 곳 어디에든 쓸 수 있어요. IntEnum 멤버로 정수 연산을 수행하면 결과 값은 열거형 상태를 잃어요.
>>> from enum import IntEnum
>>> class Number(IntEnum):
... ONE = 1
... TWO = 2
... THREE = 3
...
>>> Number.THREE
<Number.THREE: 3>
>>> Number.ONE + Number.TWO
3
>>> Number.THREE + 5
8
>>> Number.THREE == 3
True
참고 —
IntEnum과 함께auto를 쓰면 1부터 시작하는 증가하는 정수 값이 돼요.
버전 3.11에서 변경: 기존 상수 대체 사용 사례를 더 잘 지원하도록 __str__()이 이제 int.__str__()임. __format__()도 같은 이유로 이미 int.__format__()였음.
class enum.StrEnum
StrEnum은 Enum과 같지만, 그 멤버는 문자열이기도 하고 문자열을 쓸 수 있는 대부분의 같은 곳에 쓸 수 있어요. StrEnum 멤버로 수행되거나 함께 수행되는 어떤 문자열 연산의 결과도 열거형의 일부가 아니에요.
>>> from enum import StrEnum, auto
>>> class Color(StrEnum):
... RED = 'r'
... GREEN = 'g'
... BLUE = 'b'
... UNKNOWN = auto()
...
>>> Color.RED
<Color.RED: 'r'>
>>> Color.UNKNOWN
<Color.UNKNOWN: 'unknown'>
>>> str(Color.UNKNOWN)
'unknown'
참고 — 표준 라이브러리에는
str하위 클래스 대신 정확한str을 확인하는 곳이 있어요(즉isinstance(unknown, str)대신type(unknown) == str). 그런 곳에서는str(MyStrEnum.MY_MEMBER)를 사용해야 해요.
StrEnum과 함께auto를 쓰면 소문자 멤버 이름이 값이 돼요.
__str__()은 기존 상수 대체 사용 사례를 더 잘 지원하도록str.__str__()이에요.__format__()도 같은 이유로str.__format__()이에요.
버전 3.11에 추가됨.
class enum.Flag
Flag는 Enum과 같지만, 그 멤버는 비트 연산자 &(AND), |(OR), ^(XOR), ~(INVERT)를 지원하고, 그 연산의 결과는 열거형의 (별칭인) 멤버예요.
contains(self, value)
value가 self에 있으면 True를 돌려줘요.
>>> from enum import Flag, auto
>>> class Color(Flag):
... RED = auto()
... GREEN = auto()
... BLUE = auto()
...
>>> purple = Color.RED | Color.BLUE
>>> white = Color.RED | Color.GREEN | Color.BLUE
>>> Color.GREEN in purple
False
>>> Color.GREEN in white
True
>>> purple in white
True
>>> white in purple
False
iter(self)
포함된 모든 비-별칭 멤버를 돌려줘요.
>>> list(Color.RED)
[<Color.RED: 1>]
>>> list(purple)
[<Color.RED: 1>, <Color.BLUE: 4>]
버전 3.11에 추가됨.
len(self)
플래그의 멤버 수를 돌려줘요.
>>> len(Color.GREEN)
1
>>> len(white)
3
버전 3.11에 추가됨.
bool(self)
플래그에 멤버가 있으면 True, 없으면 False를 돌려줘요.
>>> bool(Color.GREEN)
True
>>> bool(white)
True
>>> black = Color(0)
>>> bool(black)
False
or(self, other)
현재 플래그에 other를 (이진) or한 결과를 돌려줘요.
>>> Color.RED | Color.GREEN
<Color.RED|GREEN: 3>
and(self, other)
현재 플래그에 other를 (이진) and한 결과를 돌려줘요.
>>> purple & white
<Color.RED|BLUE: 5>
>>> purple & Color.GREEN
<Color: 0>
xor(self, other)
현재 플래그에 other를 (이진) xor한 결과를 돌려줘요.
>>> purple ^ white
<Color.GREEN: 2>
>>> purple ^ Color.GREEN
<Color.RED|GREEN|BLUE: 7>
invert(self)
type(self)에서 self에 없는 모든 플래그를 돌려줘요.
>>> ~white
<Color: 0>
>>> ~purple
<Color.GREEN: 2>
>>> ~Color.RED
<Color.GREEN|BLUE: 6>
numeric_repr()
이름 없는 남은 숫자 값을 포맷하는 데 사용하는 함수. 기본값은 값의 repr이고, 흔한 선택은 hex()와 oct()이에요.
참고 —
Flag와 함께auto를 쓰면 1부터 시작하는 2의 거듭제곱 정수가 돼요.
버전 3.11에서 변경: 0 값 플래그의 repr()이 바뀌었어요. 이제 다음과 같아요. >>> Color(0) → <Color: 0>