PEP 354 – Python의 열거형
- Author:
- Ben Finney <ben+python at benfinney.id.au>
- Status:
- Superseded
- Type:
- Standards Track
- Created:
- 20-Dec-2005
- Python-Version:
- 2.6
- Post-History:
- 20-Dec-2005
- Superseded-By:
- 435
Table of Contents
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
거부 공지
이 PEP는 거부되었습니다. 이것은 기존 모듈(collections 등) 어디에도 잘 들어맞는 슬롯이 없으며, Python 표준 라이브러리는 개별 자료 구조를 각자의 모듈에 많이 두는 것을 피합니다. 또한 이 PEP는 폭넓은 관심을 끌지 못했습니다. 열거형이 필요한 사람들을 위해서는 이러한 요구를 충족하는 쿡북 레시피와 PyPI 패키지가 있습니다.
참고: 이 PEP는 PEP 435로 대체되었으며, 해당 PEP는 2013년 5월에 수락되었습니다.
초록
이 PEP는 Python을 위한 열거형 데이터 타입을 명세합니다.
열거형은 임의의 고유한 값에 바인딩된 기호 이름들의 배타적 집합입니다. 열거형 내의 값들은 이터레이션하고 비교할 수 있지만, 이 값들은 열거형 외부의 값들과 본질적인 관계가 없습니다.
동기
열거형의 특성은 정해진 순서는 있지만 고유한 의미는 없는, 서로 관련된 불변의 상수 값 집합을 정의하는 데 유용합니다. 고전적인 예로는 요일(일요일부터 토요일까지)과 학교 성적 등급(‘A’부터 ‘D’까지, 그리고 ‘F’)이 있습니다. 다른 예로는 오류 상태 값과 정해진 프로세스 내의 상태들이 있습니다.
서로 구별되는 임의의 값들을 나타내기 위해 int나 str 같은 다른 기본 타입의 값 시퀀스를 단순히 정의할 수도 있습니다. 그러나 열거형은 이러한 값들이 다른 어떤 값과도 구별되도록 보장하며, 의미 없는 연산(“수요일 곱하기 2”)이 이 값들에 대해 정의되지 않도록 보장합니다.
명세
열거 타입은 해당 타입의 생성자에 전달된 인자 시퀀스로부터 생성됩니다:
>>> Weekdays = enum('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat')
>>> Grades = enum('A', 'B', 'C', 'D', 'F')
값이 없는 열거형은 무의미합니다. 값 인자 없이 생성자를 호출하면 EnumEmptyError 예외가 발생합니다.
값은 새 열거형 객체의 속성에 바인딩됩니다:
>>> today = Weekdays.mon
값들은 비교할 수 있습니다:
>>> if today == Weekdays.fri:
... print "Get ready for the weekend"
열거형 내의 값들은 같은 열거형의 값들과 비교하는 경우를 제외하면 의미 있게 비교할 수 없습니다. 열거형의 값이 같은 열거형에 속하지 않거나 다른 타입인 값과 비교될 때, 비교 연산 함수는 NotImplemented [1]를 반환합니다:
>>> gym_night = Weekdays.wed
>>> gym_night.__cmp__(Weekdays.mon)
1
>>> gym_night.__cmp__(Weekdays.wed)
0
>>> gym_night.__cmp__(Weekdays.fri)
-1
>>> gym_night.__cmp__(23)
NotImplemented
>>> gym_night.__cmp__("wed")
NotImplemented
>>> gym_night.__cmp__(Grades.B)
NotImplemented
이를 통해 연산이 성공하여 불리언 값으로 평가됩니다:
>>> gym_night = Weekdays.wed
>>> gym_night < Weekdays.mon
False
>>> gym_night < Weekdays.wed
False
>>> gym_night < Weekdays.fri
True
>>> gym_night < 23
False
>>> gym_night > 23
True
>>> gym_night > "wed"
True
>>> gym_night > Grades.B
True
열거형의 값을 str로 강제 변환하면, 열거형을 생성할 때 그 값에 대해 지정했던 문자열이 됩니다:
>>> gym_night = Weekdays.wed
>>> str(gym_night)
'wed'
열거형에 속한 각 값의 순서 인덱스는 해당 값의 index 속성을 통해 정수로 노출됩니다:
>>> gym_night = Weekdays.wed
>>> gym_night.index
3
열거형은 이터레이션할 수 있으며, 열거형이 생성될 때 지정된 순서대로 값들을 반환합니다:
>>> print [str(day) for day in Weekdays]
['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat']
열거형의 값들은 해시 가능하며, 딕셔너리 키로 사용할 수 있습니다:
>>> plans = {}
>>> plans[Weekdays.sat] = "Feed the horse"
열거형의 일반적인 용도는 데이터 타입에 가능한 값들의 집합을 제공하는 것이며, 이 값들은 해당 값에 관한 다른 정보에 매핑하는 데 사용할 수 있습니다:
>>> for report_grade in Grades:
... report_students[report_grade] = \
... [s for s in students if students.grade == report_grade]
근거 – 고려했던 다른 설계들
모두 하나의 클래스에
일부 구현은 열거형과 그 값들을 모두 하나의 객체나 클래스의 속성으로 둡니다.
이 PEP는 열거형이 컨테이너이고 값은 단순한 비교 가능 객체인 설계를 규정합니다. 열거형의 모든 속성을 하나의 클래스 안에 두려고 하면 뚜렷한 이점 없이 설계가 복잡해진다고 판단했습니다.
열거형 클래스를 생성하는 메타클래스
이 PEP에서 규정하는 열거형은 enum 타입의 인스턴스입니다. 일부 대안 설계는 각 열거형을 독자적인 클래스로 구현하고, 모든 열거형의 공통 속성을 정의하는 메타클래스를 둡니다.
각 열거형마다 (인스턴스가 아닌) 클래스를 두는 한 가지 동기는 열거형의 서브클래스를 허용하여 기존 열거형을 확장하고 변경할 수 있게 하려는 것입니다. 하지만 클래스는 그 클래스의 인스턴스가 생성될 것임을 암시합니다. 각 인스턴스가 모든 요일을 담고 있는 “요일” 클래스의 인스턴스가 따로따로 여러 개 있다는 것이 무엇을 의미하는지 상상하기 어렵습니다. 이 때문에 보통 각 클래스가 싱글턴 패턴을 따르게 되어 설계가 더욱 복잡해집니다.
이와 달리, 이 PEP는 확장되거나 수정될 것으로 예상되지 않는 열거형을 규정합니다. 물론 기존 열거형의 문자열 값으로 새 열거형을 만들 수도 있고, 원한다면 enum 타입의 서브클래스를 만들 수도 있습니다.
다른 타입과 관련된 값
일부 설계는 열거된 각 값에 대해 특정 정수나 문자열 같은 다른 값과의 강한 관계를 표현합니다.
그 결과 열거형이 아무 의미도 없는 문맥에서 그런 값을 사용하게 되고, 설계가 불필요하게 복잡해집니다. 이 PEP에서 규정하는 열거된 값은 자신을 생성하는 데 사용된 값을 노출하고 다른 어떤 값과도 동등성 비교를 할 수 있지만, 열거형 밖의 값과의 순서 비교는 명시적으로 구현하지 않습니다.
열거된 값의 속성 숨기기
이전 설계에서는 열거된 값이 자신의 구현에 관해 가능한 한 많은 것을 숨겨서, 문자열 키와 순서 인덱스조차 노출하지 않았습니다.
이 PEP의 설계는 열거된 값의 열거형 타입, 순서 인덱스, 그리고 그 값에 지정된 문자열 키를 알 수 있으면 프로그램에 편리한 경우가 많다는 점을 인정합니다. 이것들은 열거된 값의 속성으로 노출됩니다.
구현
이 설계는 부분적으로 Python Cookbook의 레시피 [2]를 기반으로 합니다.
PyPI 패키지 enum [3]은 이 PEP에서 설명하는 데이터 타입의 Python 구현을 제공합니다.
참고 문헌 및 각주
Copyright
This document has been placed in the public domain.