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

Python 개선 제안 한국어 번역

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와 일관성이 있겠지만, 결과를 추가로 처리하기는 더 어려워집니다.

참고 문헌