从父函数分配variables:“分配前引用的本地variables”
对于以下Python 2.7代码:
#!/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()
我得到以下错误:
File "./a.py", line 9, in funcB c += 3 UnboundLocalError: local variable 'c' referenced before assignment
但是当我注释掉funcB
c += 3
funcB
,我得到以下输出:
funcA c 0 funcB 0 funcC 2 funcB 4 funcC 6 end
在funcB
和=
funcC
情况下,是不是正在访问c
=
? 为什么不为一个抛出错误,而不是为另一个抛出错误?
我没有select使c
变成全局variables,然后在funcB
声明global c
。 无论如何,重点不是在funcB
增加c
,而是为什么在funcB
抛出错误,而不是在funcC
抛出错误,同时访问本地或全局variables。
你在这里看到的是访问和分配variables的区别。 在Python 2.x中,只能分配给最内层或全局范围内的variables(后者是通过使用全局语句来完成的)。 您可以访问任何封闭作用域中的variables,但不能访问封闭作用域中的variables,然后在最内层或全局作用域中分配该variables。
这意味着如果在函数内部有任何赋值给名字,那么在名字被访问之前(除非使用全局语句),该名字必须已经在最内层的范围中定义。 在你的代码中, c += 3
行基本上等同于以下内容:
tmp = c c = tmp + 3
因为在函数中有一个赋值给c
的函数,那么函数中每一个c
出现只会在funcB
的本地作用域中funcB
。 这就是为什么你看到这个错误,你正试图访问c
来获取当前的+=
值,但是在本地范围内c
还没有被定义。
在Python 3中,您可以使用nonlocal语句来解决此问题,该语句允许您将variables分配给不在当前范围内,但也不在全局范围内的variables。
你的代码看起来像这样,在funcC
的顶部有一个类似的行:
def funcB(): nonlocal c c += 3 ...
在Python 2.x中,这不是一个选项,而且你可以改变非局部variables的值的唯一方法就是它是可变的。
最简单的方法是将您的值包装在一个列表中,然后在之前刚刚使用variables名称的每个位置修改并访问该列表的第一个元素:
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()
…和输出:
funcA c 0 funcB 3 funcC 5 funcB 8 funcC 5 end
funcB中的'+ ='和funcC中的'='都不是'c'吗?
不, funcC
创build一个新variables,也称为c
。 =
在这方面与+=
。
为了得到你(可能)需要的行为,将variables包装在单个元素列表中:
def outer(): c = [0] def inner(): c[0] = 3 inner() print c[0]
将打印3
。
编辑 :你会想传递c
作为参数。 Python 2没有别的办法,AFAIK,得到所需的行为。 Python 3为这些情况引入了nonlocal
关键字。
1)在funcB和=
funcC
, +=
是不是被访问?
不,因为c += 3
是一样的:
c = c + 3 ^ | and funcB does not know what this c is
2)我没有select使c
成为全局variables,然后在funcB
声明global c
。
请不要这样做,只要改变:
def funcB():
有:
def funcB(c):
然后在你的代码中调用funcB(c)
。
注意:你也应该用cosc来定义funcB
和funcC
以外的funcA
和funcA
尝试这个:
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值,那么:
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()
这将产生:
funcA c 0 funcB 3 funcC 5 funcB 8 funcC 5 end C:\Python26\
另一个肮脏的解决方法,但是,这并不需要你做全球。 一切都一样,但:
def funcB(): globals()['c'] += 3 print "funcB", c