在 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.:我是在阅读 this thread 后进行实验的.
最佳答案
key 可在 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
1 中,Python 发现您正在将一些值绑定(bind)到 a
,但发现 a
还没有已在此范围内的 global a
语句中使用并准备局部变量。然后它尝试计算表达式 a + 1
,查找变量 a
并找到一个未初始化的局部变量。这会导致 UnboundLocalError
。
在 f
2 中,Python 发现您正在为变量 a
的订阅分配一些值。它在本地 namespace 中查找该变量,但找不到。然后它沿着非本地命名空间(闭包)向上走,直到它到达全局命名空间。一旦它在全局命名空间中找不到 a
,它就会抛出一个 NameError
。
关于Python 全局变量和局部变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15594867/