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

Python 개선 제안 한국어 번역

PEP 281 – range와 xrange를 사용한 루프 카운터 반복

Author:
Magnus Lie Hetland <magnus at hetland.org>
Status:
Rejected
Type:
Standards Track
Created:
11-Feb-2002
Python-Version:
2.3
Post-History:


Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

초록

이 PEP는 for 루프에서 루프 카운터를 노출하는 또 하나의 방법을 설명합니다. 기본적으로 PEP 212의 indices() 함수 기능을 기존 함수 range()와 xrange()에 포함하자고 제안합니다.

결정

이 PEP의 저자는 PEP 279의 enumerate() 함수에 대해 논평하면서 “그 함수로 PEP 281이 쓸모없어진다면 아주 기쁘겠습니다.”라고 밝혔습니다. 이후 PEP 279는 Python 2.3에 채택되었습니다.

2005년 6월 17일, BDFL은 이 PEP가 쓸모없어졌다는 데 동의하며 이로써 이 PEP를 거부했습니다. 참고로, 그는 일부 예제의 모양이 다소 거슬린다고 보았습니다:

>>> range(range(5), range(10), range(2))
[5, 7, 9]

동기

시퀀스의 인덱스를 순회하는 것이 바람직한 경우가 많습니다. PEP 212는 이를 위한 여러 방법을 설명하며, 그중에는 indices라는 내장 함수를 추가하는 방법도 있습니다. 이 함수는 개념적으로 다음과 같이 정의됩니다:

def indices(sequence):
    return range(len(sequence))

기존 내장 함수에 기능을 추가하는 것이 새 내장 함수를 추가하는 것보다 덜 침습적일 수 있다는 가정하에, 이 PEP는 이 기능을 기존 함수 range()와 xrange()에 추가할 것을 제안합니다.

명세

내장 함수 range()와 xrange()의 세 인자 모두에 길이가 있는 객체(즉, __len__ 메서드를 구현하는 객체)를 허용할 것을 제안합니다. 인자를 정수로 해석할 수 없으면(즉, __int__ 메서드가 없으면) 대신 그 길이가 사용됩니다.

예시:

>>> range(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(range(5), range(10))
[5, 6, 7, 8, 9]
>>> range(range(5), range(10), range(2))
[5, 7, 9]
>>> list(xrange(range(10)))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(xrange(xrange(10)))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# Number the lines of a file:
lines = file.readlines()
for num in range(lines):
    print num, lines[num]

대안

위 명세의 자연스러운 대안은 xrange()가 인자에 지연 방식으로 접근하도록 허용하는 것입니다. 따라서 xrange는 인자의 길이를 명시적으로 사용하는 대신, 끝에 도달할 때까지 stop 인자의 각 요소마다 인덱스를 하나씩 반환할 수 있습니다. start와 step 인자는 반복을 시작하기 전에 길이를 계산해야 하므로, 이들에 비슷한 지연 처리를 적용하는 것은 별 의미가 없습니다. (사실 step 인자의 길이는 두 번째 요소가 반환될 때까지는 필요하지 않습니다.)

의사 구현(stop 인자만 사용하며, 그 인자가 이터러블이라고 가정합니다)은 다음과 같습니다:

def xrange(stop):
    i = 0
    for x in stop:
        yield i
        i += 1

int()를 사용할지 지연 반복을 사용할지는 __iter__ 속성이 있는지 확인하여 판단할 수 있습니다. (이 예제는 제너레이터가 있다고 가정하지만, 일반 이터레이터 객체로도 쉽게 구현할 수 있었을 것입니다.)

for 루프 안에서 인덱싱을 통해 이터러블 객체의 요소에 접근할 수 없으므로, 이 기능이 정말 유용한지는 의문일 수 있습니다.

예시:

# Printing the numbers of the lines of a file:
for num in range(file):
    print num # The line itself is not accessible

(이 문제를 해결하기 위한) 더 논란의 여지가 있는 대안은 시퀀스가 주어졌을 때 range()가 PEP 212의 irange() 함수처럼 동작하도록 하는 것입니다.

예시:

>>> range(5)
[0, 1, 2, 3, 4]
>>> range('abcde')
[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e')]

하위 호환성

__int__와 __len__을 모두 구현하는 인자(xrange를 사용한 지연 반복의 경우에는 __iter__)가 사용되면, 이 제안은 하위 호환성 문제를 일으킬 수 있습니다. 저자는 이것이 심각한 문제라고 생각하지 않습니다.