问题描述
def f(x):
b = [x]
def g(a):
b[0] -= 1
return a - b[0]
return g
工作正常。让我们对其稍作更改:
def f(x):
b = x
def g(a):
b -= 1
return a - b
return g
现在,它给出一个错误,指出b未定义!当然,可以使用nonlocal
来解决,但是我想知道为什么会首先发生这种情况?为什么可变变量是可访问的,而可变变量是不可访问的?
解决方法
从技术上讲,它与可变或不可变无关(语言不知道类型是否为“可变”)。此处的区别在于,在一种情况下,您将分配给变量,而在另一种情况下,您将从变量中读取数据。
在第二个示例中,行b -= 1
与b = b - 1
相同。您要分配给变量b
的事实将使名为b
的局部变量与名为b
的外部变量分开。由于在评估分配的右侧时尚未分配局部变量b
,因此从局部b
读取会出现错误。
在您的第一个示例中,行b[0] -= 1
与b[0] = b[0] - 1
相同。但这不是变量分配。那只是一个列表元素访问。它只是b.__setitem__(0,b.__getitem__(0) - 1)
的语法糖。您这里没有分配变量b
,您要做的只是从变量b
读取两次(以便在其指向的对象上调用方法)。由于您仅从b
中读取内容,因此它使用外部变量b
。
如果在第一个示例中,使用可变列表,像在第二个示例中一样,进行了变量赋值,则将同样创建一个局部变量,并且在赋值之前读取该局部变量也将不起作用:
def f(x):
b = [x]
def g(a):
b = [b[0] - 1]
return a - b[0]
return g