在循环内创建lambda

时间:2011-09-25 14:54:10

标签: python

  

可能重复:
  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)重写代码以使其有效吗?

3 个答案:

答案 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))