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는 “리스트 컴프리헨션”이라는 파이썬의 구문적 확장을 소개합니다. 이 PEP는 “딕셔너리 컴프리헨션(dictionary comprehension)” 또는 줄여서 “딕트 컴프리헨션(dict comprehension)”이라는 유사한 구문적 확장을 제안합니다. 딕트 컴프리헨션은 리스트 대신 파이썬 딕셔너리 객체를 생성한다는 점을 제외하면 리스트 컴프리헨션과 매우 유사한 방식으로 사용할 수 있습니다.
결정
이 PEP는 원래 파이썬 2.3에 포함시키기 위해 작성되었습니다. 이 PEP는 그 이점 대부분이 dict() 생성자와 결합된 제너레이터 표현식으로 대체될 수 있다는 관찰에 따라 철회되었습니다.
그러나 파이썬 2.7과 3.0은 이 기능을 정확히 도입했으며, 이와 밀접하게 관련된 집합 컴프리헨션(set comprehensions)도 도입했습니다. 2012년 4월 9일, 이 PEP는 상태(Status)를 Accepted로 갱신하고 Python-Version 필드를 갱신하여 이러한 현실을 반영하도록 변경되었습니다. 미해결 질문(Open Questions) 절도 현재 구현에 의해 오래전에 해결되었으므로 제거되었습니다.
제안된 해법
딕트 컴프리헨션은 대괄호 대신 중괄호로 표현식을 묶는다는 점을 제외하면 리스트 컴프리헨션과 완전히 동일합니다. 또한 for 키워드 앞의 왼쪽 부분은 콜론으로 구분된 키와 값을 모두 표현합니다. 이 표기법은 딕셔너리에 적용된 리스트 컴프리헨션을 연상시키도록 특별히 설계되었습니다.
근거
길이가 2인 시퀀스들로 이루어진 시퀀스 형태로 배열된 데이터가 있고, 이를 딕셔너리로 변환하고자 하는 경우가 있습니다. 파이썬 2.2에서 dict() 생성자는 길이가 2인 시퀀스들로 이루어진 시퀀스를 인자로 받아, 이를 (키, 값) 쌍으로 사용하여 새 딕셔너리 객체를 초기화합니다.
하지만 어떤 데이터를 길이가 2인 시퀀스들의 시퀀스로 변환하는 작업은 메모리나 성능 측면에서 불편하거나 비효율적일 수 있습니다. 또한 사물의 목록을 빠른 중복 제거나 집합 포함 검사를 위해 사물의 집합으로 변환하는 것과 같은 일부 흔한 연산의 경우, 더 나은 문법이 코드의 명료성에 도움이 될 수 있습니다.
리스트 컴프리헨션과 마찬가지로 명시적인 for 루프를 항상 사용할 수 있습니다(실제로 이는 이전 버전의 파이썬에서 유일한 방법이었습니다). 하지만 리스트 컴프리헨션과 마찬가지로, 딕셔너리 컴프리헨션은 전통적인 for 루프보다 문법적으로 더 간결한 관용구를 제공할 수 있습니다.
의미론
딕셔너리 컴프리헨션의 의미론은 사실 표준 파이썬 2.2에서 리스트 컴프리헨션을 내장 딕셔너리 생성자에 전달함으로써 실제로 보여줄 수 있습니다:
>>> dict([(i, chr(65+i)) for i in range(4)])
는 의미상 다음과 동등합니다:
>>> {i : chr(65+i) for i in range(4)}
하지만 딕셔너리 생성자 방식은 제안된 문법에 비해 두 가지 뚜렷한 단점이 있습니다. 첫째, 딕셔너리 컴프리헨션만큼 가독성이 좋지 않습니다. 둘째, 프로그래머로 하여금 먼저 메모리 내(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}
구현
모든 구현 세부 사항은 파이썬 2.7과 3.0 시기에 해결되었습니다.
Copyright
This document has been placed in the public domain.