Python變數作用域(入門必讀)

2021-09-25 01:12:07 字數 2697 閱讀 5983

在程式中定義乙個變數時,這個變數是有作用範圍的,變數的作用範圍被稱為它的作用域。

根據定義變數的位置,變數分為兩種:

每個函式在執行時,系統都會為該函式分配一塊「臨時記憶體空間」,所有的區域性變數都被儲存在這塊臨時記憶體空間內。當函式執行完成後,這塊記憶體空間就被釋放了,這些區域性變數也就失效了,因此離開函式之後就不能再訪問區域性變數了。

全域性變數意味著它們可以在所有函式內被訪問。

不管是在函式的區域性範圍內還是在全域性範圍內,都可能存在多個變數,每個變數「持有」該變數的值。從這個角度來看,不管是區域性範圍還是全域性範圍,這些變數和它們的值就像乙個「看不見」的字典,其中變數名就是字典的 key,變數值就是字典的 value。

實際上,python 提供了如下三個工具函式來獲取指定範圍內的「變數字典」:

globals():該函式返回全域性範圍內所有變數組成的「變數字典」。

locals():該函式返回當前區域性範圍內所有變數組成的「變數字典」。

vars(object):獲取在指定物件範圍內所有變數組成的「變數字典」。如果不傳入object 引數,vars() 和 locals() 的作用完全相同。

globals() 和 locals() 看似完全不同,但它們實際上也是有聯絡的,關於這兩個函式的區別和聯絡大致有以下兩點:

下面程式示範了如何使用 locals()、globals() 函式訪問區域性範圍和全域性範圍內的「變數字典」:

def test ():      age = 20      # 直接訪問age區域性變數      print(age) # 輸出20      # 訪問函式區域性範圍的「變數陣列」      print(locals()) #       # 通過函式區域性範圍的「變數陣列」訪問age變數      print(locals()['age']) # 20      # 通過locals函式區域性範圍的「變數陣列」改變age變數的值      locals()['age'] = 12      # 再次訪問age變數的值      print('***', age) # 依然輸出20      # 通過globals函式修改x全域性變數      globals()['x'] = 19  x = 5  y = 20  print(globals()) #   # 在全域性訪問內使用locals函式,訪問的是全域性變數的「變數陣列」  print(locals()) #   # 直接訪問x全域性變數  print(x) # 5  # 通過全域性變數的「變數陣列」訪問x全域性變數  print(globals()['x']) # 5  # 通過全域性變數的「變數陣列」對x全域性變數賦值  globals()['x'] = 39  print(x) # 輸出39  # 在全域性範圍內使用locals函式對x全域性變數賦值  locals()['x'] = 99  print(x) # 輸出99
從上面程式可以清楚地看出,locals() 函式用於訪問特定範圍內的所有變數組成的「變數字典」,而 globals() 函式則用於訪問全域性範圍內的全域性變數組成的「變數字典」。

在使用 globals() 或 locals() 訪問全域性變數的「變數字典」時,將會看到程式輸出的「變數字典」預設包含了很多變數,這些都是 python 主程式內建的,讀者暫時不用理會它們。

全域性變數預設可以在所有函式內被訪問,但如果在函式中定義了與全域性變數同名的變數,此時就會發生區域性變數遮蔽(hide)全域性變數的情形。例如如下程式:

name = 'charlie'  def test ():      # 直接訪問name全域性變數      print(name) # charlie  test()  print(name)
name = '孫悟空'

再次執行該程式,將會看到如下錯誤:

unboundlocalerror : local variable 『name』 referenced before assignment

該錯誤提示粗體字**所訪問的 name 變數還未定義。這是什麼原因呢?這正是由於程式在 test() 函式中增加了「name='孫悟空'」一行**造成的。

python 語法規定,在函式內部對不存在的變數賦值時,預設就是重新定義新的區域性變數。因此這行**相當於重新定義了 name 區域性變數,這樣 name 全域性變數就被遮蔽了,所以程式會報錯。

為了避免這個問題,可以通過以下兩種方式來修改上面程式:

訪問被遮蔽的全域性變數。如果希望程式依然能訪問 name 全域性變數,且在函式中可重新定義 name 區域性變數,也就是在函式中可以訪問被遮蔽的全域性變數,此時可通過 globals() 函式來實現,將上面程式改為如下形式即可:

name = 'charlie'  def test ():      # 直接訪問name全域性變數      print(globals()['name'])  # charlie      name = '孫悟空'  test()  print(name)  # charlie
在函式中宣告全域性變數。為了避免在函式中對全域性變數賦值(不是重新定義區域性變數),可使用 global 語句來宣告全域性變數。因此,可將程式改為如下形式:
name = 'charlie'  def test ():      # 宣告name是全域性變數,後面的賦值語句不會重新定義區域性變數      global name      # 直接訪問name全域性變數      print(name)  # charlie      name = '孫悟空'  test()  print(name)  # 孫悟空
增加了「global name」宣告之後,程式會把 name 變數當成全域性變數,這意味著 test() 函式後面對 name 賦值的語句只是對全域性變數賦值,而不是重新定義區域性變數。

python變數作用域

變數作用域 scope 在python中是乙個容易掉坑的地方。什麼是作用域 作用域簡單說就是乙個變數的命名空間。中變數被賦值的位置,就決定了哪些範圍的物件可以訪問這個變數,這個範圍就是命名空間。python賦值時生成了變數名,當然作用域也包括在內。python的作用域一共有4中,分別是 l loca...

Python 變數作用域

g global defchange global g g g change print g change print g 結果 global globalchange def function g function deflocalvar g local defglobalvar global g...

變數作用域 python

python 中,程式的變數並不是在哪個位置都可以訪問的,訪問許可權決定於這個變數是在 賦值的。變數的作用域決定了在哪一部分程式可以訪問哪個特定的變數名稱。python的作用域一共有4種,分別是 以 l e g b 的規則查詢,即 在區域性找不到,便會去區域性外的區域性找 例如閉包 再找不到就會去全...