在下面的Python代码中,我得到了一个UnboundLocalError
。据我所知,局部函数共享包含函数的局部变量,但这似乎不是这里的情况。我认识到a
在这种情况下是一个不可变的值,但这应该不是问题。
def outer():
a = 0
def inner():
a += 1
inner()
outer()
看起来内部函数已经收到了父函数中所有引用的副本,因为如果UnboundLocalError
的值包含在一个可变类型中,我就不会得到a
异常。
有人能够澄清这里的行为,并指出相应的Python文档吗?
答案 0 :(得分:30)
我认为你认为这是一个“可变性”问题是正确的。虽然您发布的代码会抛出“UnboundLocalError”,但以下代码不会:
def outer():
a = 0
def inner():
print a
inner()
outer()
Python不允许您从内部作用域中的外部作用域重新分配变量的值(除非您使用关键字“global”,在这种情况下不适用)。
查看本Python 2.6.2文档中“classes”文档的底部:
9.2. Python Scopes and Namespaces
[...]如果名称被声明为全局,则所有引用和分配都会进行 直接到包含模块全局名称的中间范围。 否则,在最内层范围之外找到的所有变量都是 只读(尝试写入这样的变量只会创建一个 最内层范围内的新局部变量,保持相同 命名外部变量不变)。
你的“UnboundLocalError”是因为你的函数实际上声明了一个名为“a”的新变量,然后立即尝试对其执行“+ =”操作,但这失败了,因为“a”还没有值。 (将“a + = 1”视为“a = a + 1”,如果“a”未定义,您可以看到问题。)
一般来说,如果你想要修改“a”,人们通常会绕过它的方式是使用一个可变类型来传递“a”(例如列表或字典)。您可以通过可变类型的内容修改“a”(正如您在使用此设置进行测试时可能注意到的那样)。
希望有所帮助!
答案 1 :(得分:10)
您应该将变量指定为非本地变量以在闭包中保留它的状态,因此定义应该是这样的
def outer():
a = 0
def inner():
nonlocal a
a += 1
inner()
答案 2 :(得分:9)
尝试将变量绑定为参数。
def outer():
a = 0
def inner(a=a):
a += 1
inner()
outer()
我会尝试挖掘相应的文件。
修改强>
由于您希望内部函数对外部作用域产生副作用,因此您需要使用类似列表的可变数据类型。整数和字符串是不可变的。
def outer():
a = [0]
def inner():
a[0] += 1
inner()
print a[0]
outer()