在另一个列表上应用lambda函数列表时出现意外行为

时间:2017-09-04 02:33:03

标签: python list lambda

我正在尝试创建一个函数列表,然后将其应用于数字列表。我这样做是通过迭代一系列数字,并使用for循环中的每个数字定义一个lambdas函数。然后使用第二个for循环将每个函数应用于10个数字的相同列表。

问题是我的lambdas列表似乎都取得了for循环的最终值。

fx_lst = []
for k in range(1,3,1):
    func = lambda x_: k * x_
    fx_lst.append(func)
xlst = range(1,10,1)

for fx in fx_lst:
    ylst = map(lambda xin_: fx(xin_), xlst)
    print i, ylst

ylst打印:     [2,4,6 ... 18]     [2,4,6 ... 18]

显然,我对lambdas存储变量信息的方式一无所知。

2 个答案:

答案 0 :(得分:3)

发生的事情是你的lambdas被绑定到循环变量k而不是与它相关的值,就是这样。循环变量k即使在循环之后仍然存在,因此这些lambda可以访问它。

我知道的一个可能的解决方案是lambda currying:

In [129]: fx_lst = []
     ...: for k in range(1,3,1):
     ...:     func = (lambda k=k: lambda x_: k * x_)(k)
     ...:     fx_lst.append(func)
     ...:     

In [130]: fx_lst[0](3)
Out[130]: 3

In [131]: fx_lst[1](3)
Out[131]: 6

函数(lambda k=k: lambda x_: k * x_)(k)基本上是一个高阶函数,它通过预先固定其中一个参数来减少将两个参数带到一个函数的函数。范围用k=k修复,因此外部循环变量不与lambda的范围冲突。

对于你的例子,我得到了

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[2, 4, 6, 8, 10, 12, 14, 16, 18]

另一种解决方法是使用functools.partial代替,它完全相同。

答案 1 :(得分:1)

之前我遇到过这个问题,以下是一个解决方案:

void F( ...) {...}

用法:

def apply_filters(filters, iterator):
    from functools import reduce
    return list(reduce(lambda s, f: filter(f, s), filters, iterator))