首先看一段代碼:多線程
A = 0 B = [0] def fun1(A, B): A += 1 B[0] += 1 fun1(A, B) print 'after fun1 %d %s' % (A,B) def fun2(): global A A += 1 B[0] += 1 fun2() print 'after fun2 %d %s' % (A,B)
執行後的結果:app
after fun1 0 [1]
after fun2 1 [2]
fun1中,A做爲基本類型(int)是值傳遞,B不是基本類型(list)則是引用傳遞,因此執行後全局的A未變但B變了;函數
(若是熟悉C++就很容易理解,相似的概念:指針、引用、深拷貝、淺拷貝等)spa
(注意,與C++不一樣,Python中字符串str爲基本類型)線程
fun2中,使用Python的關鍵字global才能夠在函數內操做全局變量A,但B不須要global卻能直接使用,這樣能夠避免一些「自覺得是」的邏輯錯誤;指針
(注意,若是僅僅訪問而不修改,在函數內是能夠不用global直接使用的,好比在fun2中只是print A)code
有了上面的理解後,咱們來分析下在Python中怎麼用全局變量好:blog
首先,使用基本類型的全局變量須要在每一個操做它的函數、類裏面用global聲明仍是挺麻煩的;索引
列表或元組呢,訪問的時候用數字索引會下降代碼的可讀性;字符串
用字典(dict)則能夠解決上面兩個問題,在簡單的程序中dict應該是很合適的;
可是,在複雜的代碼中若是須要對全局變量的修改進行必定的控制,或者在多組多個線程每組共享同類型但不一樣值的全局變量時,dict就沒法勝任;
綜上,我的認爲自定義一個類來保存全部的全局變量是最好的方法:
簡單時就直接訪問成員變量;
須要控制時就聲明爲私有變量,用成員函數訪問和修改;
多組多線程分開共享時就每組new一個新實例便可;
示例一:
#common.py class MyGlobal: def __init__(self): self.A = 0 self.B = [0] GL = MyGlobal() #main.py from common import * def fun(): GL.A += 1 GL.B[0] += 1 fun()
print 'after fun %d %s' % (GL.A,GL.B) #執行./main.py after fun 1 [1]
示例二:
#common.py import threading class MyGlobal: def __init__(self, i, setname): self.setname = setname self.A = i self.B = [i] #main.py from common import * def fun_trd(gl): print '%s %d %s' % (gl.setname,gl.A,gl.B) #兩組,每組三個線程 trds = [] for i in range(0,2): setname = 'SET%d' % i gl = MyGlobal(i, setname) for k in range(0,3): t = threading.Thread(target=fun_trd, args=(gl,)) t.setDaemon(True) t.start() trds.append(t) for t in trds: t.join() #執行./main.py SET0 0 [0] SET0 0 [0] SET0 0 [0] SET1 1 [1] SET1 1 [1] SET1 1 [1]
over