简体   繁体   English

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

[英]Unexpected behaviour when applying a list of lambda functions on another list

I am trying to create a list of functions that I then apply to a list of numbers. 我正在尝试创建一个函数列表,然后将其应用于数字列表。 I do this by iterating through a range of numbers, and defining a lambdas function with each number from the for loop. 我这样做是通过迭代一系列数字,并使用for循环中的每个数字定义一个lambdas函数。 Then a second for loop is used to apply each function to the same list of 10 numbers. 然后使用第二个for循环将每个函数应用于10个数字的相同列表。

The problem is that my list of lambdas seem to all take the final value of the for loop. 问题是我的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 prints: [2,4,6...18] [2,4,6...18] ylst印刷品:[2,4,6 ... 18] [2,4,6 ... 18]

Obviously I'm not understanding something about the way lambdas store variable information. 显然,我不了解lambdas存储变量信息的方式。

What's happening is that your lambdas are being bound to the loop variable k rather than the value associated with it, that's all it is. 发生的事情是你的lambdas被绑定到循环变量k而不是与它相关的值,就是这样。 The loop variable k persists even after the loop, and so those lambdas have access to it. 循环变量k甚至在循环之后仍然存在,因此这些lambda可以访问它。

One possible solution I know is lambda currying: 我知道的一个可能的解决方案是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

The function (lambda k=k: lambda x_: k * x_)(k) is basically a higher order function that reduces a function taking two parameters to a function taking one, by fixing one of the parameters constant in advance. 函数(lambda k=k: lambda x_: k * x_)(k)基本上是一个更高阶函数,它通过预先固定其中一个参数来减少将两个参数带到一个函数的函数。 The scope is fixed with k=k so the outer loop variable does not conflict with the scope of the lambda. 范围固定为k=k因此外部循环变量不与lambda的范围冲突。

For your example, I get 以你为榜样,我明白了

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

The other workaround involves using functools.partial instead, which does the exact same thing. 另一种解决方法是使用functools.partial ,它完全相同。

I run into this issue before, and the following is a solution: 我之前遇到过这个问题,以下是一个解决方案:

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

Usage: 用法:

my_filters = [lambda x: x % 2 == 0, lambda x: x % 5 == 0]
result = apply_filters(my_filters, range(1, 100))
print(result)
# [10, 20, 30, 40, 50, 60, 70, 80, 90]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM