I\'m going through some old code trying to understand what it does, and I came across this odd statement:
*x ,= p
p
is a list in t
You should always throw these to dis and see what it throws back at you; you'll see how *x, = p
is actually different from x = p
:
dis('*x, = p')
1 0 LOAD_NAME 0 (p)
2 UNPACK_EX 0
4 STORE_NAME 1 (x)
While, the simple assignment statement:
dis('x = p')
1 0 LOAD_NAME 0 (p)
2 STORE_NAME 1 (x)
(Stripping off unrelated None
returns)
As you can see UNPACK_EX
is the different op-code between these; it's documented as:
Implements assignment with a starred target: Unpacks an iterable in TOS (top of stack) into individual values, where the total number of values can be smaller than the number of items in the iterable: one of the new values will be a list of all leftover items.
Which is why, as Eugene noted, you get a new object that's referred to by the name x
and not a reference to an already existing object (as is the case with x = p
).
*x,
does seem very odd (the extra comma there and all) but it is required here. The left hand side must either be a tuple or a list and, due to the quirkiness of creating a single element tuple in Python, you need to use a trailing ,
:
i = 1, # one element tuple
If you like confusing people, you can always use the list
version of this:
[*x] = p
which does exactly the same thing but doesn't have that extra comma hanging around there.