PEP 3132 – 확장된 이터러블 언패킹
- Author:
- Georg Brandl <georg at python.org>
- Status:
- Final
- Type:
- Standards Track
- Created:
- 30-Apr-2007
- Python-Version:
- 3.0
- Post-History:
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 이터러블 언패킹 문법의 변경을 제안하며, “일반” 이름에 할당되지 않은 모든 항목의 리스트가 할당될 “모두 받는” 이름을 지정할 수 있도록 합니다.
예 하나가 천 마디 말보다 낫습니다:
>>> 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]에서 짧은 논의를 거친 후, Guido가 현재 형태로 PEP를 승인했습니다. 논의된 변경 가능 사항은 다음과 같습니다.
- exprlist에서 마지막 항목으로 별표 표현식만 허용합니다. 이렇게 하면 언패킹 코드가 조금 단순해지고 별표 표현식에 이터레이터를 할당할 수 있습니다. 이 동작은 너무 예상 밖이기 때문에 거부되었습니다.
- 별표 대상에 원본 이터러블과 동일한 타입을 제공하도록 시도합니다. 예를 들어
a, *b = 'hello'에서b는 문자열'ello'이 할당됩니다. 이는 좋아 보일 수 있지만, 모든 이터러블에 대해 일관되게 올바르게 처리하는 것은 불가능합니다. - 별표 대상을 리스트 대신 튜플로 만듭니다. 이는 함수의
*args와 일관되지만 결과를 추가로 처리하기는 더 어려워집니다.
참고 자료
Copyright
This document has been placed in the public domain.