【问题标题】:Unexpected behaviour when applying a list of lambda functions on another list在另一个列表上应用 lambda 函数列表时出现意外行为
【发布时间】:2017-09-04 02:33:03
【问题描述】:

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

问题是我的 lambda 列表似乎都采用了 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]

显然我不了解 lambda 存储变量信息的方式。

【问题讨论】:

    标签: python list lambda


    【解决方案1】:

    发生的事情是您的 lambda 被绑定到循环变量 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,它的作用完全相同。

    【讨论】:

    • 解释得很好,效果很好。谢谢你。我以前从未听说过咖喱,所以这是我需要研究的东西!
    • @user2185097 很高兴我能帮上忙!您可能对stackoverflow.com/questions/36314/what-is-currying 感兴趣
    • 您可以直接在 OP 的 lambda 定义中使用默认参数 k=k 进行即时绑定和可以说更简单的代码
    【解决方案2】:

    我之前也遇到过这个问题,解决方法如下:

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

    用法:

    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]
    

    【讨论】:

    • 你能解释一下为什么会这样吗?
    • 神奇的部分是reduce,它将一个过滤器应用于迭代器并获得一个子序列,然后将另一个过滤器应用于子序列。
    猜你喜欢
    • 2021-03-06
    • 1970-01-01
    • 2021-05-26
    • 2021-09-28
    • 2018-10-16
    • 2016-02-01
    • 2023-03-10
    • 1970-01-01
    • 2018-02-10
    相关资源
    最近更新 更多