python 變量的作用范圍


python 的變量作用域分三種

  1: local  指當前作用域

    通過locals() 能獲取該命名空間的對象的dict

  2:global 對應某個 .py 模塊的作用域 

    通過globals() 能獲取該命名空間的對象的dict

  3:builtin 最頂層的作用域。

每次執行一個函數時, 就會創建新的局部命名空間。

解釋器在檢索變量的時候會按照  local》global 》builtin 的順序檢索。

  比如檢索變量 test(只要該變量沒有被聲明為local變量,=, -=, += 這樣的操作會將變量聲明為local變量)會先從 local  檢索, 沒有檢索到則 檢索 global, 再沒檢索到則檢索 builtin. 如果最后沒有檢索到 則拋出 NameError的異常。

def space():

  a = 21
  print "local:", locals()
  print "globals:", globals()

執行該函數的輸出為:

  local: {'a': 21}
  globals: {'__builtins__': <module '__builtin__' (built-in)>, '__file__': 'space.py', '__package__': None, 'test': <function test at 0x7fe8e0535c08>, '__name__': '__main__', '__doc__': None}

 

這個栗子很好理解, 那么如果

a = 31

def space():

  a = 21
  print "local:", locals()
  print "globals:", globals()

space()

的輸出為:

  local: {'a': 21}
  globals: {'a': 31, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'space.py', '__package__': None, 'test': <function test at 0x7f7c0ec24c08>, '__name__': '__main__', '__doc__': None}

紅色的能很方便我們理解 local 和global 作用域的區別。

在函數里面, 只要有 =, +=, -= 這樣的賦值語句, 那么被賦值的變量就是local的

舉個栗子:

def t(a):
    a += 1
    print "a in function:", a
    print "locals:", locals()
a = 21
t(a)

輸出為: 

  a in function: 22
  locals: {'a': 22}
  a after invoking: 21

下面的代碼也能正常進行

def t():
    if a > 1: # 檢索a會先從local作用域檢索, 然后在檢索global作用域, 發現a = 21
        print "this a is global:", a
    print "a in function:", a
    print "locals:", locals()
a = 21
t()

而下面的代碼會報錯:

def t():
    if a > 1:
        print "this a is global:", a
    a = 3 # 此處因為有 +=, =, -= 這樣的, 所以a在該函數t內是local的, 只會在local作用域檢索a。然后上一句if a > 1會報錯
    print "a in function:", a
    print "locals:", locals()
a = 21
t()

報錯:  

  UnboundLocalError: local variable 'a' referenced before assignment

在函數里面,如果所傳的值是容引用,那么在函數里面對容器的修改也會修改 global作用域內的該容器。

def t(a):
    a['hello'] = "happy"
    print "a in function:", a
    print "locals:", locals()
a = {}
t(a)
print "a after invoking:", a

 的輸出為:

  a in function: {'hello': 'happy'}
  locals: {'a': {'hello': 'happy'}}
  a after invoking: {'hello': 'happy'}

函數的參數默認值, test_default(下面栗子的)默認值為引用類型會在使用之后一直保存,每次對默認值的修改都會保留下來, 類似與C的靜態局部變量。但是如果自己傳了一個值來替換引用的默認值, 則不會修改保留下來的默認值。

def test_default(k, v, d = {}):
    d[k] = v 
    print "d reference:", d
 
test_default("k3", "v3", d = {})  #此處傳了一個值來替換引用的默認值, 那么修改的不是默認引用的值
test_default("k1", "v1")
test_default("k2", "v2")

的輸出為:

  d reference: {'k3': 'v3'}
  d reference: {'k1': 'v1'}
  d reference: {'k2': 'v2', 'k1': 'v1'}

 

lambda 里面的默認值

funcs = [lambda x, i=i: x*i for i in range(4)]
print [func(2) for func in funcs]

的輸出為:

  [0, 2, 4, 6]

而:

funcs = [lambda x: x*i for i in range(4)]
print [func(2) for func in funcs]

的輸出為:

  [6, 6, 6, 6]

  函數在沒有執行前, 內部代碼不執行


免責聲明!

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



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