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 279enumerate() 함수에 대해 논평하면서 “이것이 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()가 자신의 인자에 지연 방식(lazy manner)으로 접근할 수 있도록 허용하는 것입니다. 따라서 길이를 명시적으로 사용하는 대신, xrange는 끝에 도달할 때까지 stop 인자의 각 요소마다 하나의 인덱스를 반환할 수 있습니다. start와 step 인자에 대해서는 이터레이션이 시작되기 전에 그 길이를 계산해야 하므로 유사한 지연 처리 방식이 거의 의미가 없습니다. (사실 step 인자의 길이는 두 번째 요소가 반환될 때까지는 필요하지 않습니다.)

(stop 인자만을 사용하고, 그것이 이터러블(iterable)이라고 가정한) 의사 구현(pseudo-implementation)은 다음과 같습니다.:

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__)가 사용되면 이 제안이 하위 호환성 문제를 일으킬 수 있습니다. 저자는 이것이 심각한 문제라고는 생각하지 않습니다.