In einer Funktion:
a += 1
wird vom Compiler als interpretiert assign to a => Create local variable a
, was nicht das ist, was Sie wollen. Es wird wahrscheinlich mit einem a not initialized
Fehler fehlschlagen , da das (lokale) a tatsächlich nicht initialisiert wurde:
>>> a = 1
>>> def f():
... a += 1
...
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in f
UnboundLocalError: local variable 'a' referenced before assignment
Sie könnten das bekommen, was Sie wollen, mit dem global
Schlüsselwort (sehr verpönt und aus guten Gründen) , wie folgt:
>>> def f():
... global a
... a += 1
...
>>> a
1
>>> f()
>>> a
2
Im Allgemeinen sollten Sie jedoch die Verwendung globaler Variablen vermeiden , die extrem schnell außer Kontrolle geraten. Dies gilt insbesondere für Multithread-Programme, bei denen Sie keinen Synchronisationsmechanismus haben, um thread1
zu wissen, wann a
Änderungen vorgenommen wurden. Kurz gesagt: Threads sind kompliziert , und Sie können kein intuitives Verständnis der Reihenfolge erwarten, in der Ereignisse auftreten, wenn zwei (oder mehr) Threads mit demselben Wert arbeiten. Die Sprache, der Compiler, das Betriebssystem, der Prozessor ... können ALLE eine Rolle spielen und entscheiden, die Reihenfolge der Operationen aus Gründen der Geschwindigkeit, der Praktikabilität oder aus anderen Gründen zu ändern.
Der richtige Weg für diese Art von Dingen besteht darin, Python-Freigabetools ( Sperren
und Freunde) zu verwenden oder Daten über eine Warteschlange zu kommunizieren, anstatt sie freizugeben, z. B.:
from threading import Thread
from queue import Queue
import time
def thread1(threadname, q):
while True:
a = q.get()
if a is None: return
print a
def thread2(threadname, q):
a = 0
for _ in xrange(10):
a += 1
q.put(a)
time.sleep(1)
q.put(None)
queue = Queue()
thread1 = Thread( target=thread1, args=("Thread-1", queue) )
thread2 = Thread( target=thread2, args=("Thread-2", queue) )
thread1.start()
thread2.start()
thread1.join()
thread2.join()
a
. Es ist das Standardblockierungsverhalten der Warteschlange, das die Synchronisierung erstellt. Die Anweisunga = q.get()
blockiert (wartet), bis ein Wert a verfügbar ist. Die Variableq
ist lokal: Wenn Sie ihr einen anderen Wert zuweisen, geschieht dies nur lokal. Die im Code zugewiesene Warteschlange ist jedoch die im Hauptthread definierte.