2012-11-30 15 views
5

Ist Sequenz entpackt Atom? Beispiel:Ist Sequenz entpackt Atom?

(a, b) = (c, d) 

Ich bin unter dem Eindruck, es ist nicht.

Edit: Ich meinte Atomarität im Zusammenhang mit Multi-Threading, d. H. Ob die gesamte Aussage unteilbar ist, wie Atome früher waren.

+1

Ich habe den Eindruck, dass Sie vielleicht mißverstehen, was * gemeinhin * von der Atomarität in der Softwareentwicklung verstanden wird. Sprechen Sie hier über Thread-Sicherheit oder fragen Sie sich, ob 'a = c' vor 'b = d' ausgeführt wird? –

+0

@MartijnPieters - Wenn OP sich über letzteres Gedanken machen würde, wäre OP sehr verwirrt, warum etwas wie '(a, b) = (b, a)' funktionieren würde, um Werte zu tauschen. Es muss eine Frage zur Fadensicherheit sein. –

+0

@TedHopp: Die Frage ist viel zu vage, um dies zu nennen, und nach meiner Erfahrung verursacht das Tupel-Entpacken eine Menge Verwirrung an und für sich. –

Antwort

6

Es ist eine Operation; der rechte Ausdruck ausgewertet wird, bevor die linke Zuordnung angewandt wird:

>>> 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) 

Oder, wenn Sie Multi-Threaded-Umgebungen zu sprechen sind über, dann ist die Zuordnung nicht Atome; der Interpreter wertet eine Tupel Zuordnung mit einem einzigen Operationscode, sondern verwendet separaten Opcodes, um dann die Ergebnisse in jede betroffenen Variablen zu speichern:

>>> 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   

jedoch normale assigment immer mindestens zwei Opcodes sein würde (ein für der rechte Ausdruck, einer zum Speichern des Ergebnisses), so in Python im Allgemeinen Assigment ist nicht atomar. Sequenz Entpacken ist nicht anders.

+1

Ich denke es nicht "atomaren" Ausdruck. sogar "j = i + 1" nicht atomar in Hochsprachen. Ich habe 'Semaphore' in Python .... Ich habe die Frage missverstanden? –

+0

Das stellt nicht wirklich fest, dass es atomar ist. Die Frage ist, ob "a" und "b" ihre Werte atomar (dh als unteilbare Operation) in einer konkurrierenden Umgebung zugewiesen bekommen. Ich glaube nicht, dass sie es sind; Das heißt, wenn '(a, b)' im letzten Schritt mit Werten '(200, 2)' enden soll, kann ein anderer Thread '(200, 10)' oder '(20, 2)' sehen. –

+0

Ich habe die Frage missverstanden (oder vielmehr, ich habe mich entschieden, die sehr spärliche Frage in Bezug auf die häufiger gestellte Frage nach Tupel-Aufgaben zu interpretieren). Ich habe es aktualisiert, um Informationen zur Thread-Sicherheit hinzuzufügen. –

4

Definitiv Atom nicht in einer Multi-Threaded-Umgebung getestet, um die folgenden Skript:

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 

Verwendung Getestete CPython 2.6, 2.7 und 3.2. Auf jeder Version druckte dieses Skript "Nicht atomar" und verschwand in weniger als einer Sekunde.

+1

Sie haben mich die Opcodes erneut überprüfen lassen; das Entpacken ist eins, aber dann gibt es zwei STORE_FAST-Opcodes, einen für jede betroffene Variable. Viele Chancen für einen anderen Thread, dazwischen etwas anderes zu vergeben. –