可能重复:
What do (lambda) function closures capture in Python?
lambda function don't closure the parameter in Python?
我正在尝试在循环中创建lambda,迭代遍历对象列表:
lambdas_list = []
for obj in obj_list:
lambdas_list.append(lambda : obj.some_var)
现在,如果我遍历lambdas列表并像这样调用它们:
for f in lambdas_list:
print f()
我得到了相同的价值。这是obj
中最后一个obj_list
的值,因为它是列表迭代器块中的最后一个变量。任何想法都能很好地(pythonic)重写代码以使其有效吗?
答案 0 :(得分:27)
请改用此行:
lambdas_list.append(lambda obj=obj: obj.some_var)
答案 1 :(得分:10)
您必须使用默认分配
捕获变量lambdas_list = [ lambda i=o: i.some_var for o in obj_list ]
或者,使用闭包来捕获变量
lambdas_list = [ (lambda a: lambda: a.some_var)(o) for o in obj_list ]
在这两种情况下,关键是确保将obj_list列表中的每个值分配给唯一的范围。
您的解决方案无效,因为从父作用域(obj
)引用了词法变量for
。
默认分配有效,因为我们从i
范围引用了lambda
。我们使用默认赋值通过使变量成为lambda
定义的一部分并因此将其作为范围的一部分来“隐藏”变量。
闭包解决方案有效,因为变量“传递”是显式的,进入立即执行的外部lambda
,从而在列表理解期间创建绑定并返回引用该变量的内部lambda
捆绑。因此,当内部lambda
实际执行时,它将引用在外部lambda
范围内创建的绑定。
答案 2 :(得分:4)
你可以这样做:
def build_lambda(obj):
return lambda : obj.some_var
lambdas_list = []
for obj in obj_list:
lambdas_list.append(build_lambda(obj))