Is sequence unpacking atomic? e.g.:
(a, b) = (c, d)
I'm under the impression it is not.
Edit: I meant atomicity in the context of multi-threading, i.e. whether the entire statement is indivisible, as atoms used to be.
It is one operation; the right-hand expression is evaluated before the left-hand assignment is applied:
>>> a, b = 10, 20 >>> a, b (10, 20) >>> b, a = a, b >>> a, b (20, 10) >>> a, b = a*b, a/b >>> a, b (200, 2)
Or, if you are talking about multi-threaded environments, then the assignment is not atomic; the interpreter evaluates a tuple assignment with a single opcode, but uses separate opcodes to then store the results into each affected variable:
>>> def t(self): a,b=20,20 ... >>> dis.dis(t) 1 0 LOAD_CONST 2 ((20, 20)) 3 UNPACK_SEQUENCE 2 6 STORE_FAST 1 (a) 9 STORE_FAST 2 (b) 12 LOAD_CONST 0 (None) 15 RETURN_VALUE
However, normal assigment is always going to be at least two opcodes (one for the right-hand expression, one for storing the result), so in python in general assigment is not atomic. Sequence unpacking is no different.
Definitely not atomic in a multi-threaded environment, tested using the following script:
import threading a, b = 10, 10 finished = False def thr(): global finished while True: # if sequence unpacking and assignment is atomic then (a, b) will always # be either (10, 10) or (20, 20). Could also just check for a != b if (a, b) in [(10, 20), (20, 10)]: print('Not atomic') finished = True break t = threading.Thread(target=thr) t.start() while True: for i in range(1000000): a, b = 20, 20 a, b = 10, 10 if finished: t.join() break
Tested using CPython 2.6, 2.7, and 3.2. On each version this script printed 'Not atomic' and exited in well under a second.