PEP 3132 – 확장된 이터러블 언패킹
- Author:
- Georg Brandl <georg at python.org>
- Status:
- Final
- Type:
- Standards Track
- Created:
- 30-Apr-2007
- Python-Version:
- 3.0
- Post-History:
Table of Contents
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 이터러블 언패킹 문법의 변경을 제안합니다. 이 변경으로 “일반” 이름에 대입되지 않은 모든 항목의 리스트가 대입되는 “나머지를 모두 받는(catch-all)” 이름을 지정할 수 있습니다.
예제 하나가 천 마디 말보다 낫습니다:
>>> a, *b, c = range(5)
>>> a
0
>>> c
4
>>> b
[1, 2, 3]
근거
많은 알고리즘에서 시퀀스를 “첫 번째, 나머지” 쌍으로 나누어야 합니다. 새 문법을 사용하면,
first, rest = seq[0], seq[1:]
위 코드가 더 깔끔하고 아마도 더 효율적인 다음 코드로 대체됩니다:
first, *rest = seq
더 복잡한 언패킹 패턴에서는 새 문법이 훨씬 더 깔끔해 보이며, 번거로운 인덱스 처리도 더 이상 필요하지 않습니다.
또한 우변의 값이 리스트가 아니라 이터러블이라면 슬라이싱을 하기 전에 리스트로 변환해야 합니다. 이 임시 리스트를 만들지 않으려면 다음과 같은 방법에 의존해야 합니다
it = iter(seq)
first = it.next()
rest = list(it)
명세
단순 대입의 왼쪽에 있는 튜플(또는 리스트)에는 별표 하나가 앞에 붙은 표현식을 최대 하나까지 포함할 수 있습니다(이하 이를 “별표” 표현식이라 부르며, 리스트의 나머지 표현식은 “필수” 표현식이라 부릅니다). 언패킹은 복합 대입에 대해서는 정의되어 있지 않습니다. 이 표현식은 언패킹되는 이터러블의 항목 중 어떤 필수 표현식에도 대입되지 않은 모든 항목의 리스트가 대입될 하위 표현식을 나타내며, 그런 항목이 없으면 빈 리스트가 대입됩니다.
예를 들어 seq가 슬라이싱 가능한 시퀀스라면, seq에 원소가 두 개 이상 있을 때 다음 대입은 모두 동등합니다:
a, b, c = seq[0], list(seq[1:-1]), seq[-1]
a, *b, c = seq
[a, *b, c] = seq
이터러블에 모든 필수 표현식에 대입할 만큼 충분한 항목이 없으면 (현재와 마찬가지로) 오류입니다.
다음과 같이 별표 표현식을 단독 대입 대상으로 사용하는 것도 오류입니다
*a = range(5)
하지만 다음은 올바른 문법입니다:
*a, = range(5)
이 제안은 for 문에서처럼 암시적 대입 문맥에 있는 튜플에도 적용된다는 점에 유의하십시오:
for a, *b in [(1, 2, 3), (4, 5, 6, 7)]:
print(b)
다음과 같이 출력합니다
[2, 3]
[5, 6, 7]
별표 표현식은 대입 대상으로만 허용되며, 그 밖의 곳에서 사용하는 것은 (물론 함수 호출의 별표 인자는 제외하고) 오류입니다.
구현
문법 변경
이 기능에는 새 문법 규칙이 필요합니다:
star_expr: ['*'] expr
이 두 규칙에서 expr이 star_expr로 변경됩니다:
comparison: star_expr (comp_op star_expr)*
exprlist: star_expr (',' star_expr)* [',']
컴파일러 변경 사항
별표 표현식을 나타내는 새 ASDL 표현식 타입 Starred가 추가됩니다. 여기서 도입되는 별표 표현식 요소는 범용적이어서, 나중에 yield *iterable 제안처럼 대입이 아닌 문맥에서 다른 용도로 사용될 수 있다는 점에 유의하십시오.
컴파일러는 별표 표현식이 유효하지 않은 모든 경우를 인식하여 문법 오류 플래그를 지정하도록 변경됩니다.
새 바이트코드 명령어 UNPACK_EX가 추가됩니다. 이 명령어의 인자는 하위 8비트에 별표 대상 앞에 있는 필수 대상의 개수를, 상위 8비트에 별표 대상 뒤에 있는 필수 대상의 개수를 담습니다. 별표 표현식이 없는 시퀀스를 언패킹할 때는 기존의 UNPACK_ITERABLE 옵코드가 유지됩니다.
바이트코드 인터프리터 변경 사항
ceval.c의 unpack_iterable() 함수는 argcntafter 매개변수를 통해 확장 언패킹을 처리하도록 변경됩니다. UNPACK_EX의 경우 이 함수는 다음 작업을 수행합니다:
- 별표가 붙은 대상 앞에 있는 필수 대상에 해당하는 모든 항목을 수집합니다
- 이터러블에 남은 모든 항목을 리스트로 수집합니다
- 별표가 붙은 대상 뒤에 있는 필수 대상에 해당하는 항목을 리스트에서 꺼냅니다
- 개별 항목과 크기가 조정된 리스트를 스택에 푸시합니다
리스트나 튜플처럼 타입이 알려진 이터러블을 언패킹하는 지름길을 추가할 수 있습니다.
현재 구현은 SourceForge 패치 트래커 [SFPATCH]에서 찾을 수 있습니다. 이제 최소한의 테스트 케이스도 포함되어 있습니다.
수락
python-3000 메일링 리스트 [1]에서 짧은 논의를 거친 후, 이 PEP는 현재 형태 그대로 Guido에 의해 채택되었습니다. 논의된 변경 가능성은 다음과 같습니다:
- 별표가 붙은 표현식을 exprlist의 마지막 항목으로만 허용합니다. 이렇게 하면 언패킹 코드가 조금 단순해지고, 별표가 붙은 표현식에 이터레이터를 할당할 수 있게 됩니다. 이 동작은 지나치게 예상 밖이라는 이유로 거부되었습니다.
- 별표가 붙은 대상에 원본 이터러블과 같은 타입을 부여하려고 시도합니다. 예를 들어
a, *b = 'hello'에서b에는 문자열'ello'가 할당됩니다. 좋아 보일 수는 있지만, 모든 이터러블에 대해 일관되게 올바로 처리하는 것은 불가능합니다. - 별표가 붙은 대상을 리스트 대신 튜플로 만듭니다. 이렇게 하면 함수의
*args와 일관성이 있겠지만, 결과를 추가로 처리하기는 더 어려워집니다.
참고 문헌
Copyright
This document has been placed in the public domain.