Python全局变量和局部变量

时间:2013-03-24 03:29:50

标签: python scope global-variables

在Python 2.7中,运行以下代码:

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()

我得到了不同的错误:

Traceback (most recent call last):
  File "test.py", line 4, in <module>
    f()
  File "test.py", line 2, in f
    a[0] = a[0] + 1
NameError: global name 'a' is not defined

为什么认为a的{​​{1}}是int的局部变量,list时是全局的?这背后的理由是什么?

P.S。:我在阅读this thread后进行了实验。

2 个答案:

答案 0 :(得分:5)

密钥可在the assignment statement的文档中找到:

  

将对象分配给单个目标以递归方式定义为   如下:

     

如果目标是标识符(名称)(例如a = a + 1

     
      
  • 如果名称未出现在当前代码的全局语句中   block:名称绑定到当前本地名称空间中的对象。
  •   
  • 否则:名称绑定到当前全局中的对象   命名空间。
  •   
     

如果该名称已被绑定,该名称将被反弹。这可能会导致   先前绑定到该名称的对象的引用计数   达到零,导致对象被解除分配及其析构函数   (如果有的话)被召唤。

     

...

     

如果目标是订阅(例如a[0] = a[0] + 1:主要表达式   评估参考。它应该产生可变序列   对象(如列表)或映射对象(如字典)。   接下来,评估下标表达式。

f 1 中,Python看到您将某个值绑定到a,看到a中没有使用global a此范围内的语句并准备局部变量。然后它尝试评估表达式a + 1,查找变量a并找到未初始化的局部变量。这会产生UnboundLocalError

f 2 中,Python发现您正在为变量a的订阅分配一些值。它在本地命名空间中查找该变量并且无法找到它。然后它会遍历非本地命名空间(闭包),直到它到达全局命名空间。一旦在全局命名空间中找不到a,它就会抛出NameError

答案 1 :(得分:-1)

你可以尝试这样做:

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

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

g()