PEP 274 – 딕셔너리 컴프리헨션
- Author:
- Barry Warsaw <barry at python.org>
- Status:
- Final
- Type:
- Standards Track
- Created:
- 25-Oct-2001
- Python-Version:
- 2.7, 3.0
- Post-History:
- 29-Oct-2001
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
PEP 202는 “리스트 컴프리헨션”이라는 Python 문법 확장을 도입합니다. 이 PEP는 “딕셔너리 컴프리헨션”, 줄여서 “dict 컴프리헨션”이라고 부르는 비슷한 문법 확장을 제안합니다. 딕셔너리 컴프리헨션은 리스트 컴프리헨션과 매우 비슷한 방식으로 사용할 수 있으며, 다만 리스트 객체 대신 Python 딕셔너리 객체를 만들어 낸다는 점이 다릅니다.
결정
이 PEP는 원래 Python 2.3에 포함되기 위해 작성되었습니다. 이 PEP의 이점은 사실상 모두 제너레이터 표현식과 dict() 생성자를 함께 사용하는 방법으로 대체된다는 점이 확인되어 철회되었습니다.
하지만 Python 2.7과 3.0에서 바로 이 기능이 도입되었으며, 이와 밀접하게 관련된 집합 컴프리헨션도 함께 도입되었습니다. 2012-04-09에 이 PEP는 Status를 Accepted로 갱신하고 Python-Version 필드를 갱신하여 이러한 현실을 반영하도록 수정되었습니다. 미해결 질문 섹션도 삭제되었습니다. 해당 질문들은 현재 구현에서 이미 오래전에 해결되었기 때문입니다.
제안하는 해결책
dict 컴프리헨션은 대괄호 대신 중괄호로 표현식을 묶는다는 점을 제외하면 리스트 컴프리헨션과 똑같습니다. 또한 for 키워드 앞의 왼쪽 부분은 콜론으로 구분된 키와 값을 모두 나타냅니다. 이 표기법은 딕셔너리에 적용한 리스트 컴프리헨션을 떠올리게 하도록 특별히 설계되었습니다.
근거
데이터가 길이 2인 시퀀스들의 시퀀스로 구성되어 있고, 이를 딕셔너리로 바꾸고 싶을 때가 있습니다. Python 2.2에서 dict() 생성자는 길이가 2인 시퀀스들의 시퀀스를 인자로 받으며, 이 시퀀스들은 새 딕셔너리 객체를 초기화하는 (키, 값) 쌍으로 사용됩니다.
하지만 데이터를 길이 2인 시퀀스들의 시퀀스로 바꾸는 작업은 번거로울 수 있고, 메모리나 성능 면에서 비효율적일 수 있습니다. 또한 중복을 빠르게 제거하거나 집합 포함 여부를 검사하려고 항목의 리스트를 항목의 집합으로 바꾸는 것과 같은 몇몇 흔한 작업에서는 더 나은 문법이 코드를 명확하게 하는 데 도움이 될 수 있습니다.
리스트 컴프리헨션과 마찬가지로, 명시적인 for 루프는 언제든 사용할 수 있습니다(실제로 이전 버전의 Python에서는 이것이 유일한 방법이었습니다). 하지만 리스트 컴프리헨션과 마찬가지로 dict 컴프리헨션은 전통적인 for 루프보다 문법적으로 더 간결한 관용구를 제공할 수 있습니다.
의미론
딕셔너리 컴프리헨션의 의미는 내장 딕셔너리 생성자에 리스트 컴프리헨션을 전달하여 기본 Python 2.2에서도 실제로 보여 줄 수 있습니다:
>>> dict([(i, chr(65+i)) for i in range(4)])
이는 의미상 다음과 동등합니다:
>>> {i : chr(65+i) for i in range(4)}
하지만 딕셔너리 생성자를 사용하는 방식은 제안된 문법과 비교해 뚜렷한 단점이 두 가지 있습니다. 첫째, dict 컴프리헨션만큼 읽기 쉽지 않습니다. 둘째, 프로그래머가 먼저 메모리 내(in-core) 리스트 객체를 만들어야 하는데, 이는 비용이 클 수 있습니다.
예시
>>> print {i : chr(65+i) for i in range(4)}
{0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}
>>> print {k : v for k, v in someDict.iteritems()} == someDict.copy()
1
>>> print {x.lower() : 1 for x in list_of_email_addrs}
{'barry@zope.com' : 1, 'barry@python.org' : 1, 'guido@python.org' : 1}
>>> def invert(d):
... return {v : k for k, v in d.iteritems()}
...
>>> d = {0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}
>>> print invert(d)
{'A' : 0, 'B' : 1, 'C' : 2, 'D' : 3}
>>> {(k, v): k+v for k in range(4) for v in range(4)}
... {(3, 3): 6, (3, 2): 5, (3, 1): 4, (0, 1): 1, (2, 1): 3,
(0, 2): 2, (3, 0): 3, (0, 3): 3, (1, 1): 2, (1, 0): 1,
(0, 0): 0, (1, 2): 3, (2, 0): 2, (1, 3): 4, (2, 2): 4, (
2, 3): 5}
구현
모든 구현 세부 사항은 Python 2.7과 3.0 시기에 해결되었습니다.
Copyright
This document has been placed in the public domain.