PEP 279 – enumerate() 내장 함수
- Author:
- Raymond Hettinger <python at rcn.com>
- Status:
- Final
- Type:
- Standards Track
- Created:
- 30-Jan-2002
- Python-Version:
- 2.3
- Post-History:
Table of Contents
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 흔히 사용되는 반복 관용구를 단순화하기 위해 새로운 내장 함수 enumerate()를 도입합니다. 이 함수는 iteritems()가 딕셔너리에 제공하는 것과 같은 이점 – 간결하고 읽기 쉬우며 신뢰할 수 있는 인덱스 표기법 – 을 모든 이터러블 컬렉션에 제공합니다.
근거
Python 2.2는 PEP 234에서 제안된 이터러블 인터페이스 개념을 도입했습니다. iter() 팩토리 함수가 공통 호출 규약으로 제공되었으며, Python 전반에 걸쳐 이터레이터를 통합 주제로 사용하도록 깊은 변경이 이루어졌습니다. 이 통합은 매핑, 시퀀스, 파일 객체에 대한 공통 이터러블 인터페이스를 확립하는 형태로 이루어졌습니다.
제너레이터는 PEP 255에서 제안된 것으로, 특히 내부 실행 과정이 복잡하거나 상태가 가변적인 이터레이터를 더 쉽게 생성하기 위한 수단으로 도입되었습니다. 제너레이터의 가용성 덕분에 PEP 212의 루프 카운터 아이디어를 개선할 수 있게 되었습니다. 이러한 아이디어들은 인덱스와 값을 함께 순회하는 깔끔한 구문을 제공했지만, 모든 이터러블 객체에 적용되지는 않았습니다. 또한 그 접근 방식은 전체 시퀀스를 한 번에 평가하지 않는 제너레이터가 제공하는 메모리 친화적 이점을 갖지 못했습니다.
새로운 제안은 이터레이터와 제너레이터가 사용 가능해지면서 비로소 가능해진 내장 함수 enumerate()를 추가하는 것입니다. 이 함수는 iteritems()가 딕셔너리에 제공하는 것과 같은 이점 – 간결하고 읽기 쉬우며 신뢰할 수 있는 인덱스 표기법 – 을 모든 이터러블에 제공합니다. zip()과 마찬가지로, 이 함수는 널리 사용되는 반복 관용구가 될 것으로 예상됩니다.
이 제안은 기존 구현을 활용하도록 설계되어 있으며, 통합하는 데 추가 노력이 거의 필요하지 않습니다. 이는 하위 호환성을 가지며 새로운 키워드가 필요하지 않습니다. 이 제안은 제너레이터가 확정되어 더 이상 __future__에서 임포트되지 않을 때 Python 2.3에 포함될 예정입니다.
BDFL 선언
새로운 내장 함수는 승인되었습니다(ACCEPTED).
새로운 내장 함수의 명세
def enumerate(collection):
'Generates an indexed series: (0,coll[0]), (1,coll[1]) ...'
i = 0
it = iter(collection)
while 1:
yield (i, it.next())
i += 1
참고 A: PEP 212 루프 카운터 이터레이션에서는 인덱싱을 구현하기 위한 여러 제안을 논의했습니다. 그 제안들 중 일부는 리스트에만 동작하는 반면, 위의 함수는 모든 제너레이터, xrange, 시퀀스, 이터러블 객체에 대해 동작합니다. 또한 그 제안들은 제너레이터가 없던 Python 2.2 이전 세계에서 제시되고 평가되었습니다. 그 결과 PEP 212의 제너레이터를 사용하지 않는 버전은 거대한 튜플 리스트로 메모리를 소비한다는 단점이 있었습니다. 여기서 제시된 제너레이터 버전은 빠르고 가벼우며, 모든 이터러블에서 동작하고, 사용자가 계산 노력의 손실 없이 중간에 시퀀스를 포기할 수 있게 해줍니다.
정수 이터레이터, 정수 for-루프, 그리고 range와 xrange의 인자를 수정하는 것 등 관련 문제를 다루는 다른 PEP들이 있습니다. enumerate() 제안은 다른 제안들을 배제하지 않으며, 그 제안들이 채택되더라도 여전히 중요한 요구 – 모든 이터러블에서 항목의 개수를 세는 요구 – 를 충족시킵니다. 다른 제안들은 인덱스를 생성하는 수단은 제공하지만, 이에 대응하는 값은 제공하지 않습니다. 이는 파일 객체, 제너레이터, 또는 __getitem__으로 정의된 시퀀스처럼 임의 접근을 지원하지 않는 시퀀스가 주어질 경우 특히 문제가 됩니다.
참고 B: PEP 검토자 거의 전원이 이 함수를 환영했지만, 내장 함수로 두어야 하는지에 대해서는 의견이 갈렸습니다. 별도 모듈로 두어야 한다는 주장의 주된 근거는 언어의 팽창 속도를 늦추기 위함이었습니다. 내장 함수로 두어야 한다는 주장의 주된 근거는 이 함수가 이터러블 인터페이스를 갖춘 모든 객체에 적용 가능한, 핵심적인 프로그래밍 스타일의 일부가 될 운명이라는 것이었습니다. zip()이 여러 시퀀스에 걸쳐 반복하는 문제를 해결하듯이, enumerate() 함수는 반복 카운터 문제를 해결합니다.
내장 함수를 단 하나만 허용해야 한다면, enumerate()가 가장 중요한 범용 도구이며, 프로그램의 간결성, 명확성 및 신뢰성을 높이는 동시에 가장 폭넓은 부류의 문제를 해결합니다.
참고 C: 다양한 대체 이름들이 논의되었습니다:
iterindexed() |
다섯 음절은 발음하기 번거롭습니다 |
index() |
좋은 동사이지만 .index() 메서드와 혼동될 수 있습니다 |
indexed() |
널리 선호되었으나 형용사는 피해야 합니다 |
indexer() |
명사라서 for 루프에서 읽기가 좋지 않았습니다 |
count() |
직접적이고 명시적이지만 다른 문맥에서 자주 사용됩니다 |
itercount() |
직접적이고 명시적이지만 여러 사람이 싫어했습니다 |
iteritems() |
딕셔너리의 key:value 개념과 충돌합니다 |
itemize() |
amap.items()가 list(itemize(amap))와 다르기
때문에 혼란스럽습니다 |
enum() |
간결하지만 enumerate보다 명확성이 떨어지고, 다른 언어에서 다른 의미로 쓰이는 enum과 너무 유사합니다 |
‘count’가 들어간 이름들은 모두 카운트가 0이 아니라 1부터 시작한다는 인상을 준다는 추가적인 단점이 있었습니다.
‘index’가 들어간 이름들은 모두, 인덱싱이 선형적 순서화가 아니라 정렬 작업을 의미하는 데이터베이스 언어의 용법과 충돌했습니다.
참고 D: 이 함수는 원래 선택적인 start 및 stop 인자와 함께 제안되었습니다. GvR은 함수 호출 enumerate(seqn,4,6)이 시퀀스의 네 번째와 다섯 번째 요소를 반환하는 슬라이스로도 그럴듯하게 해석될 수 있다는 점을 지적했습니다. 이러한 모호함을 피하기 위해, 반복 카운터로서의 유연성을 잃게 되는 것을 감수하고서라도 선택적 인자를 제거했습니다. 그러한 유연성은 다음과 같이 1부터 세는 흔한 경우에 가장 중요했습니다:
for linenum, line in enumerate(source,1): print linenum, line
- GvR의 논평:
filter와map은 사라져서 리스트 컴프리헨션으로 흡수되어야 하며, 변종을 더 늘려서는 안 됩니다. 저는 차라리 이터레이터 대수를 수행하는 내장 함수를 도입하고 싶습니다(예를 들어 제가 예시로 자주 사용해 온 iterzip과 같은 것 말입니다).시퀀스와 그 인덱스 집합을 병렬로 순회할 수 있는 방법이 있다는 아이디어가 마음에 듭니다. 이것이 내장 함수여도 괜찮습니다.
“indexed”라는 이름은 마음에 들지 않습니다. 형용사는 좋은 함수 이름이 되지 못합니다. 어쩌면
iterindexed()는 어떻습니까?- Ka-Ping Yee의 의견:
- 저 역시 당신이 제안한 모든 것에 상당히 만족합니다… 그리고 추가된 내장 함수들(특히 정말로 ‘indexed’)은 제가 오랫동안 원해 왔던 것들입니다.
- Neil Schemenauer의 의견:
- 새로운 내장 함수들은 괜찮게 들립니다. Guido는 내장 함수의 수가 너무 많이 늘어나는 것을 우려할 수도 있습니다. 이를 모듈의 일부로 홍보하는 편이 더 나을 수도 있습니다. 모듈을 사용한다면 유용한 함수를 많이 추가할 수 있습니다(Haskell에는 우리가 훔쳐올 만한 함수가 많이 있습니다).
- Magnus Lie Hetland를 위한 의견:
- indexed는 유용하고 자연스러운 내장 함수가 될 것이라고 생각합니다. 저는 분명히 이것을 자주 사용할 것입니다.
indexed()가 정말 마음에 듭니다; +1입니다. 저는 이것이 PEP 281을 구식으로 만드는 것에 매우 만족합니다. 이터레이터 유틸리티를 위한 별도의 모듈을 추가하는 것은 좋은 생각인 것 같습니다. - 커뮤니티의 의견:
enumerate()제안에 대한 반응은 거의 100% 호의적이었습니다. 거의 모든 사람들이 이 아이디어를 마음에 들어 했습니다.- 작성자의 답변:
- 이 의견들 이전에는 네 가지 내장 함수가 제안되었습니다. 의견 이후
xmap,xfilter,xzip은 철회되었습니다. 남은 하나는 이 언어에 필수적이며 단독으로 제안된 것입니다.Indexed()는 구현하기 매우 쉬우며 몇 분 안에 문서화할 수 있습니다. 더 중요한 것은, 그렇지 않으면 제너레이터를 명시적으로 사용하지 않는 일상적인 프로그래밍에서도 이것이 유용하다는 점입니다.이 제안에는 원래
iterzip()이라는 또 다른 함수가 포함되어 있었습니다. 그것은 이후itertools모듈의izip()함수로 구현되었습니다.
Copyright
This document has been placed in the public domain.