討論下python中全局變量的使用


首先看一段代碼:

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)

執行后的結果:

after fun1 0 [1]
after fun2 1 [2]

fun1中,A作為基本類型(int)是值傳遞,B不是基本類型(list)則是引用傳遞,所以執行后全局的A未變但B變了;

(如果熟悉C++就很容易理解,類似的概念:指針、引用、深拷貝、淺拷貝等)

注意,與C++不同,Python中字符串str為基本類型

fun2中,使用Python的關鍵字global才可以在函數內操作全局變量A,但B不需要global卻能直接使用,這樣可以避免一些“自以為是”的邏輯錯誤;

(注意,如果僅僅訪問而不修改,在函數內是可以不用global直接使用的,比如在fun2中只是print A)

 

有了上面的理解后,我們來分析下在Python中怎么用全局變量好:

首先,使用基本類型的全局變量需要在每個操作它的函數、類里面用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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM