1

为什么 lambda 函数要获取值列表 i = 4 。在调用 lambda 期间,封闭范围不存在。函数 f 已完成工作并返回控制(变量 i 不存在)。

def f():
    L = []
    for i in range(5): 
        L.append(lambda x: i ** x) 
    return L
L = f()
L[0]



def f1(N):
    def f2(X):
        return X**N
    return f2
f=f1(2) 
f (3)  
 9
g = f1(3)
g(3)
27
f(3)
9
4

1 回答 1

9

Python 使用闭包来捕获对原始变量的引用。lambda对象保留对名称的引用,i通过它可以访问值。这意味着i变量在完成后继续存在f

.__closure__您可以在 lambda 对象的元组中内省此闭包;函数具有相同的属性:

>>> L[0].__closure__
(<cell at 0x1077f8b78: int object at 0x107465880>,)
>>> L[0].__closure__[0]
<cell at 0x1077f8b78: int object at 0x107465880>
>>> L[0].__closure__[0].cell_contents
4

这也是为什么列表中的所有lambda都L引用 value 4,而不是数字 0 到 4 的原因。它们都引用同一个闭包:

>>> L[0].__closure__[0] is L[1].__closure__[0]
True

闭包是指变量,而不是定义闭包时该变量的值。在循环结束i时最后设置为4,因此当i在 lambda 闭包中查找时,4将找到列表中的所有 lambda。

i如果您希望您的 lambda在循环期间引用 的值,请在关键字参数中捕获它:

def f():
    L = []
    for i in range(5): 
        L.append(lambda x, i=i: i ** x) 
    return L

Nowi是 lambda 的局部变量,而不是闭包。

或者,创建一个全新的范围来绘制闭包:

def create_lambda(i):
    return lambda x: i ** x

def f():
    return [create_lambda(i) for i in range(5)]

现在create_lambda()是一个新的范围,它有自己的本地i供 lambda 闭包引用。然后每个 lambdas 都有自己的闭包:

>>> L[0].__closure__[0] is L[1].__closure__[0]
False

闭包是指特定命名空间中的变量;每次调用函数时都会创建一个新的本地命名空间,因此每个闭包都在一个单独的命名空间中引用iin与其他对.create_lambdacreate_lambda

于 2013-06-18T11:36:16.163 回答