从父函数分配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来定义funcBfuncC以外的funcAfuncA

尝试这个:

 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