How does it work under the hood? I don't understand the reason for the errors below:
>>> def f():
... yield 1,2
... yield 3,4
...
>>> *f()
File "<stdin>", line 1
*f()
^
SyntaxError: invalid syntax
>>> zip(*f())
[(1, 3), (2, 4)]
>>> zip(f())
[((1, 2),), ((3, 4),)]
>>> *args = *f()
File "<stdin>", line 1
*args = *f()
^
SyntaxError: invalid syntax
The *iterable
syntax is only supported in an argument list of a function call (and in function definitions).
In Python 3.x, you can also use it on the left-hand side of an assignment, like this:
[*args] = [1, 2, 3]
For this particular example, this is actually equivalent to
args = [1, 2, 3]
The version using argument unpacking creates a shallow copy of the list, but when using a list literal on the right-hand side of the assignment, this difference is not observable.
The syntax is more commonly used with multiple assignment targets on the left-hand side:
head, *tail = some_list
This assigns the first element of some_list
to head
and the remainder (potentially empty) to tail
. It will throw a ValueError
if some_list
is empty, since then there's nothing to assign to head
.
While you can use the argument unpacking syntax to create a shallow copy of a list, I wouldn't recommend it for that purpose, since it kind of hides your intention. So instead of
[*a] = some_list
I'd write
a = some_list.copy()
It's slightly longer, but the intention is much clearer.