wim
wim

Reputation: 362657

Iterable unpacking and slice assignment

L = [0, 1, 2]
L[::2], *rest = "abcdef"
print(L, rest)

Expected output:

['a', 1, 'b'] ['c', 'd', 'e', 'f']

Actual output:

ValueError: attempt to assign sequence of size 1 to extended slice of size 2

Is using unpacking assignment in combination with extended slice assignment not possible for some reason? Why? I don't see anything obvious in PEP 3132 -- Extended Iterable Unpacking or in the Python datamodel suggesting this shouldn't be valid.

Upvotes: 5

Views: 333

Answers (1)

blhsing
blhsing

Reputation: 106543

This is not a bug. Unpacking is always done by mapping each item in the right-hand iterable to the corresponding comma-separated left-hand expression when there are more than one left-hand expressions. The L[::2] expression in your example is just one of the two left-hand expressions, and it therefore receives just one item from unpacking the right-hand iterable while the starred left-hand expression receives the rest.

As the rationale in PEP-3132 points out:

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

your:

L[::2], *rest = "abcdef"

is therefore equivalent to:

L[::2], rest = "a", "bcdef"

which would thus result in the said error of ValueError: attempt to assign sequence of size 1 to extended slice of size 2 since "a" cannot be further unpacked for a slice of 2.

If Python were to add your interpretation of unpacking into the syntax, it can make, for example, the statement of:

L[::2], *rest = "ab", "c", "d"

ambiguous--should L become ["a", 1, "b"] and rest become ["c", "d"], or should L become ["ab", 1, "c"], and rest become ["d"]? Always allotting one item in the iterable per LHS expression makes the interpretation much clearer and less prone to runtime errors.

Upvotes: 6

Related Questions