Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

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-루프, 그리고 rangexrange의 인자를 수정하는 것 등 관련 문제를 다루는 다른 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의 논평:
filtermap은 사라져서 리스트 컴프리헨션으로 흡수되어야 하며, 변종을 더 늘려서는 안 됩니다. 저는 차라리 이터레이터 대수를 수행하는 내장 함수를 도입하고 싶습니다(예를 들어 제가 예시로 자주 사용해 온 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() 함수로 구현되었습니다.