[Python學習] 專題六.區域性變數、全域性變數global、匯入模組變數

weixin_33766168發表於2015-09-27

        定義在函式內的變數有區域性作用域,在一個模組中最高階別的變數有全域性作用域。本文主要講述全域性變數、區域性變數和匯入模組變數的方法。
        參考:《Python核心程式設計 (第二版)》

一. 區域性變數

        宣告適用的程式的範圍被稱為了宣告的作用域。在一個過程中,如果名字在過程的宣告之內,它的出現即為過程的區域性變數;否則出現即為非區域性。例:

def foo(x):
    print 'x = ',x
    x = 200
    print 'Changed in foo(), x = ',x
    
x = 100
foo(x)
print 'x = ',x
        輸出結果如下:
>>> 
x =  100
Changed in foo(), x =  200
x =  100
        在主塊中定義x=100,Python使用函式宣告的形參傳遞x至foo()函式。foo()中把x賦值為200,x是函式的區域性變數;所以在函式內改變x的值,主塊中定義的x不受影響。
        核心筆記:
        當搜尋一個識別符號時,Python先從區域性作用域開始搜尋。如果在區域性作用域內沒有找到那個名字,那麼一定會在全域性域找到這個變數,否則會被丟擲NameError異常。
        作用域的概念和用於找到變數的名稱空間搜尋順序相關。當一個函式執行時,所有在區域性名稱空間的名字都在區域性作用域內;當查詢一個變數時,第一個被搜尋的名稱空間,如果沒有找到那個變數,那麼就可能找到同名的區域性變數。

二. 全域性變數

        全域性變數的一個特徵是除非刪除掉,否則它們存活到指令碼執行結束,且對於所有的函式,它們的值都是可以被訪問的。然而區域性變數,就像它們存放的棧,暫時地存在,僅僅只依賴於定義它們的函式現階段是否處於活動。當一個函式呼叫出現時,其區域性變數就進入宣告它們的作用域。在那一刻,一個新的區域性變數名為那個物件建立了,一旦函式完成,框架被釋放,變數將會離開作用域。

X = 100
def foo():
    global X
    print 'foo() x = ',X
    X = X + 5
    print 'Changed in foo(), x = ',X

def fun():
    global X
    print 'fun() x = ',X
    X = X + 1
    print 'Changed in fun(), x = ',X
    
if __name__ == '__main__':
    foo()
    fun()
    print 'Result x = ',X
        輸出結果如下:
>>> 
foo() x =  100
Changed in foo(), x =  105
fun() x =  105
Changed in fun(), x =  106
Result x =  106
        核心筆記:
        使用global語句定義全域性變數。當使用全域性變數同名的區域性變數時要小心,如果將全域性變數的名字宣告在一個函式體內,全域性變數的名字能被區域性變數給覆蓋掉。所以,你應該儘量新增global語句,否則會使得程式的讀者不清楚這個變數在哪裡定義的。
        你可以使用同一個global語句指定多個全域性變數。例如global x, y, z。
        當我在製作Python爬蟲時,需要想函式中傳遞url,迴圈爬取每個url頁面的InfoBox,此時的檔案寫入操作就可以有兩種方法實現:1.通過傳遞引數file;2.通過定義全域性變數file。
SOURCE = open("F:\\test.txt",'w')
def writeInfo(i):
    global SOURCE
    SOURCE.write('number'+str(i)+'\n')

def main():
    i=0
    while i<50:
        writeInfo(i)
        print i
        i=i+1
    else:
        print 'End'
    SOURCE.close()

main() 
       PS:在此種用法中,如果我們在函式writeInfo()中不使用global 宣告全域性變數SOURCE,其實也可以使用,但是此時應該是作為一個內部變數使用,由於沒有初始值,因此報錯。Python查詢變數是順序是:先區域性變數,再全域性變數。
UnboundLocalError: local variable 'SOURCE' referenced before assignment

三. 模組匯入變數

        主要方法是通過在py檔案中模組定義好變數,然後通過import匯入全域性變數並使用。例:

import global_abc
def foo():
    print global_abc.GLOBAL_A
    print global_abc.GLOBAL_B
    print global_abc.GLOBAL_C
    global_abc.GLOBAL_C = global_abc.GLOBAL_C + 200
    print global_abc.GLOBAL_C
    
if __name__ == '__main__':
    foo()
    print global_abc.GLOBAL_A + ' ' + global_abc.GLOBAL_B
    print global_abc.GLOBAL_C
        輸出如下所示,全域性變數結構是可以改變的。
>>> 
hello
world
300
500
hello world
500
        截圖如下所示:


        PS:應該儘量避免使用全域性變數。不同的模組都可以自由的訪問全域性變數,可能會導致全域性變數的不可預知性。對全域性變數,如果程式設計師甲修改了_a的值,程式設計師乙同時也要使用_a,這時可能導致程式中的錯誤。這種錯誤是很難發現和更正的。同時,全域性變數降低了函式或模組之間的通用性,不同的函式或模組都要依賴於全域性變數。同樣,全域性變數降低了程式碼的可讀性,閱讀者可能並不知道呼叫的某個變數是全域性變數,但某些情況不可避免的需要使用它。

        最後關於閉包和Lambda(相當於函式)就不再介紹,希望文章對你有所幫助~同時今天也是中秋節,祝所有程式猿和讀者中秋節快樂。
 
        (By:Eastmount 2015-9-27 下午4點   http://blog.csdn.net/eastmount/)


相關文章