シーケンスの解凍はアトミックですか?例えば:
(a, b) = (c, d)
私はそうではないという印象を受けています。
編集:マルチスレッドのコンテキストでの原子性、つまり、以前のアトムのように、ステートメント全体が分割できないかどうかを意味しました。
シーケンスの解凍はアトミックですか?例えば:
(a, b) = (c, d)
私はそうではないという印象を受けています。
編集:マルチスレッドのコンテキストでの原子性、つまり、以前のアトムのように、ステートメント全体が分割できないかどうかを意味しました。
これは1つの操作です。右側の式は、左側の割り当てが適用される前に評価されます。
>>> 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)
または、マルチスレッド環境について話している場合、割り当てはアトミックではありません。インタプリタは単一のオペコードを使用してタプルの割り当てを評価しますが、個別のオペコードを使用して、影響を受ける各変数に結果を格納します。
>>> 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
ただし、通常の割り当ては常に少なくとも2つのオペコード(1つは右辺の式用、もう1つは結果の格納用)になるため、Pythonでは一般に割り当てはアトミックではありません。シーケンスのアンパックも例外ではありません。
次のスクリプトを使用してテストされた、マルチスレッド環境では明らかにアトミックではありません。
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
CPython 2.6、2.7、および3.2を使用してテストされています。各バージョンで、このスクリプトは「アトミックではありません」と出力し、1秒以内に終了しました。