关于python:在循环中创建lambda

Creating lambda inside a loop

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
What do (lambda) function closures capture in Python?
lambda function don't closure the parameter in Python?

我尝试在循环内创建lambda,循环迭代对象列表:

1
2
3
lambdas_list = []
for obj in obj_list:
   lambdas_list.append(lambda : obj.some_var)

现在,如果我遍历lambdas列表并这样调用它们:

1
2
for f in lambdas_list:
    print f()

我得到同样的值。这是obj_list中最后一个obj的值,因为它是列表迭代器块中的最后一个变量。有没有好的(Python式的)重写代码的想法让它工作?


改为使用此行:

1
lambdas_list.append(lambda obj=obj: obj.some_var)


您或者必须使用默认分配捕获变量

1
lambdas_list = [ lambda i=o: i.some_var for o in obj_list ]

或者,使用闭包捕获变量

1
lambdas_list = [ (lambda a: lambda: a.some_var)(o) for o in obj_list ]

在这两种情况下,关键是确保obj_列表中的每个值都分配给一个唯一的作用域。

您的解决方案不起作用,因为词汇变量obj是从父作用域(for)引用的。

由于我们引用了lambda范围中的i,因此默认分配工作正常。我们使用缺省赋值使变量"传递"成为lambda定义的一部分,从而使其成为范围的一部分。

闭包解决方案之所以起作用,是因为变量"passing"是显式的,它进入外部lambda,然后立即执行,从而在列表理解期间创建绑定,并返回引用该绑定的内部lambda。因此,当内部lambda实际执行时,它将引用在外部lambda范围中创建的绑定。


你可以这样做:

1
2
3
4
5
6
def build_lambda(obj):
  return lambda : obj.some_var

lambdas_list = []
for obj in obj_list:
   lambdas_list.append(build_lambda(obj))