2013-03-24 222 views
4

在Python 2.7,運行下面的代碼:Python的全局和局部變量

def f(): 
    a = a + 1 

f() 

給出以下結果:

Traceback (most recent call last): 
    File "test.py", line 4, in <module> 
    f() 
    File "test.py", line 2, in f 
    a = a + 1 
UnboundLocalError: local variable 'a' referenced before assignment 

但是,如果我的代碼更改爲以下:

def f(): 
    a[0] = a[0] + 1 

f() 
我得到了不同的錯誤:

爲什麼Python考慮a是一個局部變量,當它是一個int,全局是list?這背後的理由是什麼?

P.S .:我在閱讀this thread後進行了實驗。

回答

5

的關鍵是在文檔中發現the assignment statement

Assignment of an object to a single target is recursively defined as follows.

If the target is an identifier (name) (e. g. a = a + 1):

  • If the name does not occur in a global statement in the current code block: the name is bound to the object in the current local namespace.
  • Otherwise: the name is bound to the object in the current global namespace.

The name is rebound if it was already bound. This may cause the reference count for the object previously bound to the name to reach zero, causing the object to be deallocated and its destructor (if it has one) to be called.

...

If the target is a subscription (e. g. a[0] = a[0] + 1): The primary expression in the reference is evaluated. It should yield either a mutable sequence object (such as a list) or a mapping object (such as a dictionary). Next, the subscript expression is evaluated.

f Python看到你正在結合一定的價值到a,看到a尚未在此範圍內的global a語句中使用並準備本地變量。然後它嘗試評估表達式a + 1,查找變量a並找到未初始化的局部變量。這導致了UnboundLocalError

f Python發現您正在爲訂閱變量a分配一些值。它在本地命名空間中查找該變量,但無法找到它。然後它遍歷非本地名稱空間(閉包),直到它到達全局名稱空間。一旦它在全局命名空間中找不到a,它將拋出一個NameError

+0

我認爲這個錯誤與g中的賦值無關。我編輯了刪除無關語句的問題。 – fossilet 2013-03-24 03:52:00

+0

@fossilet - 道歉,我誤以爲你的問題 - 我更新了我的答案,讓我知道它是否有幫助。 – 2013-03-24 04:39:30

-1

你能嘗試做這樣的事情:

def f(a): 
    a += 1 
    print a 

def g(): 
    a = 3 
    f(a) 

g()