【问题标题】:Lazy evaluation when use lambda and list comprehension [duplicate]使用 lambda 和列表理解时的延迟评估 [重复]
【发布时间】:2018-10-31 15:10:20
【问题描述】:

这是示例 python 代码。

f_list = [lambda x : x ** i for i in range(5)]
[f_list[j](10) for j in range(5)]

我认为输出应该是:

[10, 100, 1000, 10000]

但我得到了这个:

[10000, 10000, 10000, 10000]

我想知道当我运行这段代码时实际发生了什么。以及与惰性求值有什么联系。

【问题讨论】:

  • 在某处肯定有重复。简而言之,您的函数不是i 的闭包; f_list 中的每个函数都是 exact 相同的函数,其主体引用了一个全局变量 i,当函数被调用时会查找其值。
  • 结果是[10000, 10000, 10000, 10000, 10000]
  • 是的,因为列表中的每个函数在被调用时都会看到i == 4,因为这是列表理解分配给i 的最后一个值。在计算 lambda 表达式以生成函数时 i 的值是无关紧要的。
  • 对于 Python 3(更正我的原始评论),i 不是全局变量,而是特定于列表理解但由所有函数共享的非局部变量
  • @AndyK 我只是忘记了“0”

标签: python python-3.x lazy-evaluation


【解决方案1】:

这是一个很好的例子,说明为什么柯里化是好的,你可以像这样柯里化你的函数来实现你的目标:

f_list = [(lambda y : lambda x : x ** y)(i) for i in range(5)]
r = [f_list[j](10) for j in range(5)]

结果将是:

=> [1, 10, 100, 1000, 10000]

柯里化:

理解 curry 对我来说是什么的简单方法是下一个,而不是给一个函数它需要的所有参数,你创建一个函数,它总是接收一个参数,然后返回另一个函数,它再次接受一个参数,并在最终函数中,使用所有参数进行所需的转换

一个小例子:

sum_curry = lambda x : lambda y : x + y

这里你有一个简单的求和函数,但是假设你想要函数 plus_one,好的,你可以像这样重用上面的函数:

plus_one = sum_curry(1)

【讨论】:

  • 你可能会提到柯里化(不是“柯里化”)是什么,因为它在 Python 中不是一个常见的概念。 (更好的是,为什么这是必要的。)
  • @chepner 我希望现在有点清楚了
  • 它确实让代码更加pythonic。谢谢!
  • @chaos_ko 欢迎您!不要忘记总是接受一个答案,你最喜欢的,用✓左上角
猜你喜欢
  • 2016-09-12
  • 2012-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-14
  • 2021-05-17
相关资源
最近更新 更多