Python的闭包与nonlocal
2009 10 15 11:16 AM 9000次查看
可在Python中却不是这样,这让我非常头疼。简单来说,在Python 2.x中,闭包只能读外部函数的变量,而不能改写它。
举例来说,这样是合法的:
def a():
x = 0
def b():
print locals()
y = x + 1
print locals()
print x, y
return b
a()()
结果:{'x': 0}而这样是非法的:
{'y': 1, 'x': 0}
0 1
def a():
x = 0
def b():
print locals()
y = x + 1
print locals()
x = 1
print x, y
return b
a()()
结果:{}可以看到,print locals()和y = x + 1这2步并没有对x赋值,但x就已经找不到了。
Traceback (most recent call last):
File "C:\Documents and Settings\Administrator\Desktop\oo.py", line 11, in <mod
ule>
a()()
File "C:\Documents and Settings\Administrator\Desktop\oo.py", line 5, in b
y = x + 1
UnboundLocalError: local variable 'x' referenced before assignment
同时也可看出,Python代码在解释执行时,并非像BASIC一样一句一句解释,而会将一整个代码块预先做些处理。
要在Python 2.x中解决这个问题,目前只能使用全局变量:
x = 0
def a():
global x
x += 1
def b():
global x
x += 1
print x
return b
a()()
结果:2但全局变量在任何语言中都不被提倡,因为它很难控制,这也是我之前所说的头疼的原因。此外,在函数内访问全局变量需要用global声明,而且连读取都要,这比JavaScript麻烦多了。
为了解决这个问题,Python 3.x引入了nonlocal关键字(详见The nonlocal statement)。
只要在闭包内用nonlocal声明变量,就可以让解释器在外层函数中查找变量名了,例如:
def a():
x = 0
def b():
nonlocal x
x += 1
print x
return b
a()()
结果:1虽然声明方式和JavaScript正好相反,但总算是解决了使用全局变量的问题。只可惜Python 2.x中应该是看不到了…
顺便八卦一下,使用nonlocal作为关键字的原因是为了避免与已有的源代码冲突,以下就是Python SVN在2006年11月5日的扫描结果:
nonlocal 0
use 2
using 3
reuse 4
free 8
outer 147
向下滚动可载入更多评论,或者点这里禁止自动加载。