Assigning to variable from parent function: “Local variable referenced before assignment”
对于以下python 2.7代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #!/usr/bin/python def funcA(): print"funcA" c = 0 def funcB(): c += 3 print"funcB", c def funcC(): print"funcC", c print"c", c funcB() c += 2 funcC() c += 2 funcB() c += 2 funcC() print"end" funcA() |
我得到以下错误:
1 2 3 | File"./a.py", line 9, in funcB c += 3 UnboundLocalError: local variable 'c' referenced before assignment |
但当我在
1 2 3 4 5 6 7 | funcA c 0 funcB 0 funcC 2 funcB 4 funcC 6 end |
在
我没有选择使
您在这里看到的是访问和分配变量之间的区别。在python 2.x中,只能将变量分配给最里面的作用域或全局作用域(后者是通过使用global语句完成的)。可以访问任何封闭范围中的变量,但不能访问封闭范围中的变量,然后在最内部或全局范围中分配给它。
这意味着,如果对函数内部的名称进行了任何赋值,则在访问该名称之前,必须在最内部的作用域中定义该名称(除非使用了全局语句)。在您的代码中,行
1 2 | tmp = c c = tmp + 3 |
由于函数中有对
在python 3中,您可以通过使用非本地语句来解决这个问题,该语句允许您将变量分配给不在当前范围内,但也不在全局范围内的变量。
您的代码应该是这样的,在
1 2 3 4 | def funcB(): nonlocal c c += 3 ... |
在python 2.x中,这不是一个选项,唯一可以更改非局部变量值的方法是变量是否可变。
最简单的方法是将值包装在一个列表中,然后在以前使用变量名的每个位置修改和访问该列表的第一个元素:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def funcA(): print"funcA" c = [0] def funcB(): c[0] += 3 print"funcB", c[0] def funcC(): c[0] = 5 print"funcC", c[0] print"c", c[0] funcB() funcC() funcB() funcC() print"end" funcA() |
…和输出:
1 2 3 4 5 6 7 | funcA c 0 funcB 3 funcC 5 funcB 8 funcC 5 end |
Isn't 'c' being accessed in both cases of '+=' in funcB and '=' in funcC?
不,
要获得您(可能)想要的行为,请将变量包装在单个元素列表中:
1 2 3 4 5 6 | def outer(): c = [0] def inner(): c[0] = 3 inner() print c[0] |
将打印
编辑:你想把
1)在funcb中的
不,因为
1 2 3 4 | c = c + 3 ^ | and funcB does not know what this c is |
2)我没有选择让
请不要这样做,只需更改:
1 | def funcB(): |
用:
1 | def funcB(c): |
稍后在代码中调用
注:您还应该对
另一个肮脏的解决方案,但是,它不要求您使C成为全局的。一切都一样,但:
1 2 3 | def funcB(): globals()['c'] += 3 print"funcB", c |
试试这个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def funcA(): print"funcA" c = 0 def funcB(c): c += 3 print"funcB", c def funcC(c): c = 5 print"funcC", c print"c", c funcB(c) funcC(c) funcB(c) funcC(c) print"end" funcA() |
如果你想记住c值,那么:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | def funcA(): print"funcA" c = 0 def funcB(c): c += 3 print"funcB", c return c def funcC(c): c = 5 print"funcC", c return c print"c", c c = funcB(c) c = funcC(c) c = funcB(c) c = funcC(c) print"end" funcA() |
这将产生:
1 2 3 4 5 6 7 8 9 | funcA c 0 funcB 3 funcC 5 funcB 8 funcC 5 end C:\Python26\ |