Movatterモバイル変換


[0]ホーム

URL:


Following system colour schemeSelected dark colour schemeSelected light colour scheme

Python Enhancement Proposals

PEP 3132 – Extended Iterable Unpacking

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

Abstract

This PEP proposes a change to iterable unpacking syntax, allowing tospecify a “catch-all” name which will be assigned a list of all itemsnot assigned to a “regular” name.

An example says more than a thousand words:

>>>a,*b,c=range(5)>>>a0>>>c4>>>b[1, 2, 3]

Rationale

Many algorithms require splitting a sequence in a “first, rest” pair.With the new syntax,

first,rest=seq[0],seq[1:]

is replaced by the cleaner and probably more efficient:

first,*rest=seq

For more complex unpacking patterns, the new syntax looks evencleaner, and the clumsy index handling is not necessary anymore.

Also, if the right-hand value is not a list, but an iterable, ithas to be converted to a list before being able to do slicing; toavoid creating this temporary list, one has to resort to

it=iter(seq)first=it.next()rest=list(it)

Specification

A tuple (or list) on the left side of a simple assignment (unpackingis not defined for augmented assignment) may contain at most oneexpression prepended with a single asterisk (which is henceforthcalled a “starred” expression, while the other expressions in thelist are called “mandatory”). This designates a subexpression thatwill be assigned a list of all items from the iterable being unpackedthat are not assigned to any of the mandatory expressions, or anempty list if there are no such items.

For example, ifseq is a sliceable sequence, all the followingassignments are equivalent ifseq has at least two elements:

a,b,c=seq[0],list(seq[1:-1]),seq[-1]a,*b,c=seq[a,*b,c]=seq

It is an error (as it is currently) if the iterable doesn’t containenough items to assign to all the mandatory expressions.

It is also an error to use the starred expression as a loneassignment target, as in

*a=range(5)

This, however, is valid syntax:

*a,=range(5)

Note that this proposal also applies to tuples in implicit assignmentcontext, such as in afor statement:

fora,*bin[(1,2,3),(4,5,6,7)]:print(b)

would print out

[2,3][5,6,7]

Starred expressions are only allowed as assignment targets, using themanywhere else (except for star-args in function calls, of course) is anerror.

Implementation

Grammar change

This feature requires a new grammar rule:

star_expr:['*']expr

In these two rules,expr is changed tostar_expr:

comparison:star_expr(comp_opstar_expr)*exprlist:star_expr(','star_expr)*[',']

Changes to the Compiler

A new ASDL expression typeStarred is added which represents astarred expression. Note that the starred expression elementintroduced here is universal and could later be used for otherpurposes in non-assignment context, such as theyield*iterableproposal.

The compiler is changed to recognize all cases where a starredexpression is invalid and flag them with syntax errors.

A new bytecode instruction,UNPACK_EX, is added, whose argumenthas the number of mandatory targets before the starred target in thelower 8 bits and the number of mandatory targets after the starredtarget in the upper 8 bits. For unpacking sequences without starredexpressions, the oldUNPACK_ITERABLE opcode is kept.

Changes to the Bytecode Interpreter

The functionunpack_iterable() in ceval.c is changed to handlethe extended unpacking, via anargcntafter parameter. In theUNPACK_EX case, the function will do the following:

  • collect all items for mandatory targets before the starred one
  • collect all remaining items from the iterable in a list
  • pop items for mandatory targets after the starred one from the list
  • push the single items and the resized list on the stack

Shortcuts for unpacking iterables of known types, such as lists ortuples, can be added.

The current implementation can be found at the SourceForge Patchtracker[SFPATCH]. It now includes a minimal test case.

Acceptance

After a short discussion on the python-3000 list[1], the PEP wasaccepted by Guido in its current form. Possible changes discussedwere:

  • Only allow a starred expression as the last item in the exprlist.This would simplify the unpacking code a bit and allow for thestarred expression to be assigned an iterator. This behavior wasrejected because it would be too surprising.
  • Try to give the starred target the same type as the sourceiterable, for example,b ina,*b='hello' would beassigned the string'ello'. This may seem nice, but isimpossible to get right consistently with all iterables.
  • Make the starred target a tuple instead of a list. This would beconsistent with a function’s*args, but make further processingof the result harder.

References

[SFPATCH]
https://bugs.python.org/issue1711529
[1]
https://mail.python.org/pipermail/python-3000/2007-May/007198.html

Copyright

This document has been placed in the public domain.


Source:https://github.com/python/peps/blob/main/peps/pep-3132.rst

Last modified:2025-02-01 08:59:27 GMT


[8]ページ先頭

©2009-2025 Movatter.jp