Python 闭包

来源:互联网 发布:淘宝客户管理系统 编辑:程序博客网 时间:2024/05/18 02:55

理解 Python 闭包,感到困惑的点:

>>> x = 1>>> def f():    y = []    def ff():        y += [11] # 问题应该是出现在变量名的使用上        return y    return ff>>> l = f()>>> l()Traceback (most recent call last):  File "<pyshell#144>", line 1, in <module>    l()  File "<pyshell#142>", line 4, in ff    y += [11]UnboundLocalError: local variable 'y' referenced before assignment# 抛出未绑定的局部变量异常,为什么呢? OK,换一种写法:>>> def f():    y = []    def ff():        y.append(11)        return y    return ff>>> l = f()>>> l()[11]>>> l()[11, 11]>>> l()[11, 11, 11]# 一切正常

那上面为什么会抛出UnboundLocalError异常呢?再换一种写法:

>>> def f():    y = [0]    def ff():        y[0] += 1 # 修改变量的引用,不会抛出异常        return y    return ff>>> l = f()>>> l()[1]>>> l()[2]>>> l()[3]

总结:
一个函数的调用需要读取或修改该函数外部作用域的变量时:
1. 直接读取该变量,(变量解析的 LEGB 法则,即标识符的搜索顺序:Local -> Enclosing(直接外围空间) -> Global -> Builtin),在任何一层找到该变量即停止搜索,若直到 Builtin 层仍未找到该变量则抛出NameError异常;
2. 若需要修改变量,确保操作该变量的引用,否则抛出UnboundLocalError异常。


Lambda 、作用域

lambda 定义了新的作用域,使用 lambda 与 def 定义的函数,在作用域方面没有本质的不同。都是在函数调用时按照 LEGB 顺序解析变量。

>>> x = 5>>> def f():...     y = 10...     bar = lambda : x + y...     print bar() # bar() 被调用使按 LEGB 顺序解析变量...     y = 0...     print bar() # 同上>>>f()155