Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 533
wim Avatar asked Apr 30 '19 18:04

wim


People also ask

What is iterable unpacking?

Introduction. Unpacking in Python refers to an operation that consists of assigning an iterable of values to a tuple (or list ) of variables in a single assignment statement. As a complement, the term packing can be used when we collect several values in a single variable using the iterable unpacking operator, * .

What is the difference between unpacking tuple and tuple assignment give example for each?

Python tuples are immutable means that they can not be modified in whole program. Packing and Unpacking a Tuple: In Python, there is a very powerful tuple assignment feature that assigns the right-hand side of values into the left-hand side. In another way, it is called unpacking of a tuple of values into a variable.

When would you use multiple assignment statement to unpack a tuple?

Multiple assignment (also known as tuple unpacking or iterable unpacking) allows you to assign multiple variables at the same time in one line of code. This feature often seems simple after you've learned about it, but it can be tricky to recall multiple assignment when you need it most.

What is the purpose of unpacking tuples?

Unpacking tuples means assigning individual elements of a tuple to multiple variables. Use the * operator to assign remaining elements of an unpacking assignment into a list and assign it to a variable.


1 Answers

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.

like image 112
blhsing Avatar answered Sep 25 '22 20:09

blhsing