W funkcji:
a += 1
zostanie zinterpretowany przez kompilator jako assign to a => Create local variable a
, co nie jest tym, czego chcesz. Prawdopodobnie zakończy się niepowodzeniem z a not initialized
błędem, ponieważ (lokalny) a rzeczywiście nie został zainicjowany:
>>> 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
Możesz dostać to, czego chcesz, ze global
słowem kluczowym (bardzo niezadowolonym i nie bez powodu) , na przykład:
>>> def f():
... global a
... a += 1
...
>>> a
1
>>> f()
>>> a
2
Generalnie jednak należy unikać używania zmiennych globalnych, które bardzo szybko wymykają się spod kontroli. Jest to szczególnie ważne w przypadku programów wielowątkowych, w których nie ma żadnego mechanizmu synchronizacji, thread1
aby wiedzieć, kiedy a
został zmodyfikowany. Krótko mówiąc: wątki są skomplikowane i nie można oczekiwać intuicyjnego zrozumienia kolejności, w jakiej zachodzą zdarzenia, gdy dwa (lub więcej) wątki działają na tej samej wartości. Język, kompilator, system operacyjny, procesor ... WSZYSTKIE mogą odgrywać rolę i decydować o zmianie kolejności operacji ze względu na szybkość, praktyczność lub z jakiegokolwiek innego powodu.
Właściwym sposobem na tego typu rzeczy jest użycie narzędzi do udostępniania w Pythonie ( blokad
i znajomych) lub lepiej, przesyłanie danych za pośrednictwem kolejki zamiast ich udostępniania, np. W ten sposó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()