Understanding *x ,= lst
It's a feature that was introduced in Python 3.0 (PEP 3132). In Python 2, you could do something like this:
>>> p = [1, 2, 3]
>>> q, r, s = p
>>> q
1
>>> r
2
>>> s
3
Python 3 extended this so that one variable could hold multiple values:
>>> p = [1, 2, 3]
>>> q, *r = p
>>> q
1
>>> r
[2, 3]
This, therefore, is what is being used here. Instead of two variables to hold three values, however, it is just one variable that takes each value in the list. This is different from x = p
because x = p
just means that x
is another name for p
. In this case, however, it is a new list that just happens to have the same values in it. (You may be interested in "Least Astonishment" and the Mutable Default Argument)
Two other common ways of producing this effect are:
>>> x = list(p)
and
>>> x = p[:]
Since Python 3.3, the list object actually has a method intended for copying:
x = p.copy()
The slice is actually a very similar concept. As nneonneo pointed out, however, that works only with objects such as lists and tuples that support slices. The method you mention, however, works with any iterable: dictionaries, sets, generators, etc.
*x ,= p
is basically an obfuscated version of x = list(p)
using extended iterable unpacking. The comma after x
is required to make the assignment target a tuple (it could also be a list though).
*x, = p
is different from x = p
because the former creates a copy of p
(i.e. a new list) while the latter creates a reference to the original list. To illustrate:
>>> p = [1, 2]
>>> *x, = p
>>> x == p
True
>>> x is p
False
>>> x = p
>>> x == p
True
>>> x is p
True