2013-03-24 130 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()