Python全局变量和局部变量

5
在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

为什么Python认为a是局部变量,但当它是int类型时是全局变量,而当它是list类型时又是局部变量呢?这背后的原理是什么?
P.S.:我在阅读这篇帖子后进行了一些实验。
2个回答

7
关键在于赋值语句的文档中找到:
将对象分配给单个目标的递归定义如下。
如果目标是标识符(名称)(例如a = a + 1):
- 如果名称没有出现在当前代码块中的全局语句中:名称绑定到当前本地命名空间中的对象。 - 否则:名称绑定到当前全局命名空间中的对象。
如果名称已经绑定,则重新绑定名称。这可能会导致先前绑定到名称的对象的引用计数达到零,从而导致对象被释放并调用其析构函数(如果有)。
如果目标是订阅(例如a [0] = a [0] + 1):评估引用中的主要表达式。它应该产生一个可变序列对象(例如列表)或映射对象(例如字典)。接下来,评估下标表达式。
f1中,Python看到您将某个值绑定到a,发现a在此范围内没有在global a语句中使用,并准备了一个本地变量。然后它尝试评估表达式a + 1,查找变量a并找到一个未初始化的本地变量。这导致了UnboundLocalError
f2中,Python看到您正在将某个值分配给变量a的订阅。它在本地命名空间中查找该变量并找不到它。然后它向上遍历非本地命名空间(闭包),直到它到达全局命名空间。一旦在全局命名空间中找不到a,它就会抛出一个NameError

我认为错误与g中的任务无关。我已经编辑了问题,删除了不相关的陈述。 - Fish Monitor
@fossilet - 抱歉我误解了你的问题 - 我已更新我的答案,如果有帮助请告诉我。 - Sean Vieira

-1

你能试着做这样的事情吗:

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

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

g()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接