PEP 3142 – 제너레이터 표현식에 “while” 절 추가
- Author:
- Gerald Britton <gerald.britton at gmail.com>
- Status:
- Rejected
- Type:
- Standards Track
- Created:
- 12-Jan-2009
- Python-Version:
- 3.0
- Post-History:
- Resolution:
- Python-Dev message
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 기존의 “if” 절을 보완하는 “while” 절을 추가하여 제너레이터 표현식을 개선할 것을 제안합니다.
근거
제너레이터 표현식(PEP 289)은 동적으로 생성된 객체를 리스트 컴프리헨션(PEP 202)에 제공하는 간결한 방법입니다. 현재 제너레이터 표현식에서는 “if” 절을 사용하여 반환되는 객체를 특정 기준을 충족하는 것으로 걸러낼 수 있습니다. 그러나 “if” 절은 반환될 수 있는 모든 객체에 대해 평가되므로, 경우에 따라서는 특정 시점 이후의 모든 객체가 거부될 수도 있습니다. 예를 들어:
g = (n for n in range(100) if n*n < 50)
이는 제너레이터 함수(PEP 255)를 사용하는 다음 코드와 동등합니다:
def __gen(exp):
for n in exp:
if n*n < 50:
yield n
g = __gen(iter(range(10)))
0, 1, 2, 3, 4, 5, 6, 7을 산출하지만, 8부터 99까지의 숫자도 검사하여 모두 거부합니다. 해당 범위의 숫자에서는 n*n >= 50이기 때문입니다. “while” 절을 허용하면 불필요한 검사를 단락(short-circuit)시킬 수 있습니다:
g = (n for n in range(100) while n*n < 50)
역시 0, 1, 2, 3, 4, 5, 6, 7을 산출하지만, 조건(n*n < 50)이 더 이상 참이 아니므로 8에서 멈춥니다. 이는 다음 제너레이터 함수와 동등합니다:
def __gen(exp):
for n in exp:
if n*n < 50:
yield n
else:
break
g = __gen(iter(range(100)))
현재 같은 결과를 얻으려면 위와 같은 제너레이터 함수를 작성하거나 itertools의 takewhile 함수를 사용해야 합니다:
from itertools import takewhile
g = takewhile(lambda n: n*n < 50, range(100))
takewhile 코드는 제안된 문법과 같은 결과를 얻지만, 더 길고 (누군가는 “덜 우아하다”고 말할) 방식으로 얻습니다. 또한 takewhile 버전은 추가 함수 호출(위 예제의 lambda)이 필요하며, 그에 따른 성능 저하가 있습니다. 간단한 테스트에 따르면 다음 코드는:
for n in (n for n in range(100) if 1): pass
다음 코드보다 약 10% 더 나은 성능을 보입니다:
for n in takewhile(lambda n: 1, range(100)): pass
두 코드가 비슷한 결과를 내는데도 그렇습니다. (첫 번째 예제는 제너레이터를 사용하고, takewhile은 이터레이터입니다.) 비슷한 방식으로 구현한다면, “while” 절은 현재의 “if” 절과 거의 같은 성능을 보일 것입니다.
독자는 “if” 절과 “while” 절이 상호 배타적이어야 하는지 물을 수 있습니다. 두 절을 함께 유용하게 사용할 수 있는 경우가 있음을 보여 주는 좋은 예들이 있습니다. 예를 들어:
p = (p for p in primes() if p > 100 while p < 1000)
소수를 산출하는 primes() 제너레이터가 있다고 가정하면, 이 코드는 100과 1000 사이의 소수를 반환해야 합니다.
제너레이터 표현식에 “while” 절을 추가하면 간결한 형태를 유지하면서도 표현식을 단락시키는 유용한 기능을 더할 수 있습니다.
감사의 글
Raymond Hettinger가 2002년 1월에 제너레이터 표현식의 개념을 처음 제안했습니다.
Copyright
This document has been placed in the public domain.