Lambdas里面的列表理解

ube*_*kel 7 python lambda functional-programming list-comprehension

我希望有一个lambdas列表,它可以作为一些高速计算的缓存,并注意到这一点:

>>> [j() for j in [lambda:i for i in range(10)]]
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
Run Code Online (Sandbox Code Playgroud)

虽然

>>> list([lambda:i for i in range(10)])
[<function <lambda> at 0xb6f9d1ec>, <function <lambda> at 0xb6f9d22c>, <function <lambda> at 0xb6f9d26c>, <function <lambda> at 0xb6f9d2ac>, <function <lambda> at 0xb6f9d2ec>, <function <lambda> at 0xb6f9d32c>, <function <lambda> at 0xb6f9d36c>, <function <lambda> at 0xb6f9d3ac>, <function <lambda> at 0xb6f9d3ec>, <function <lambda> at 0xb6f9d42c>]
Run Code Online (Sandbox Code Playgroud)

这意味着lambda是唯一的函数,但它们在某种程度上都共享相同的索引值.

这是一个错误还是一个功能?我该如何避免这个问题?它不仅限于列表理解......

>>> funcs = []
... for i in range(10):
...     funcs.append(lambda:i)
... [j() for j in funcs]
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]
Run Code Online (Sandbox Code Playgroud)

int*_*jay 15

lambda返回的值i在调用它的时候.由于lambda在循环完成运行后调用,因此值i始终为9.

您可以i在lambda中创建一个局部变量来保存lambda定义时的值:

>>> [j() for j in [lambda i=i:i for i in range(10)]]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)

另一种解决方案是创建一个返回以下内容的函数lambda:

def create_lambda(i):
    return lambda:i
>>> [j() for j in [create_lambda(i) for i in range(10)]]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为i每次调用都会创建一个不同的闭包(保持不同的值)create_lambda.

  • 太糟糕了,我不能给两个答案都给绿色标记.我选择了这个,因为它实际上提供了正确的代码来剪切和粘贴,就像我是五个,我喜欢这种方法来解答SO. (2认同)
  • 干杯.如果我熟悉语法,我想我也会这样做; 但使用`k`让我看到哪个字母映射到in-lambda变量,哪个字符映射到理解变量. (2认同)

Jos*_*ton 9

你在这里看到的是封闭的影响.lambda正在从稍后使用的程序中捕获状态.因此,虽然每个lambda都是唯一的对象,但状态不一定是唯一的.

这里的实际'gotchya' i是捕获变量,而不是i在该时间点表示的值.我们可以用一个更简单的例子来说明这一点:

>>> y = 3
>>> f = lambda: y
>>> f()
3
>>> y = 4
>>> f()
4
Run Code Online (Sandbox Code Playgroud)

lambda保持对变量的引用,并在执行lambda时计算该变量.

要解决此问题,您可以在lambda中分配一个局部变量:

>>> f = lambda y=y:y
>>> f()
4
>>> y = 6
>>> f()
4
Run Code Online (Sandbox Code Playgroud)

最后,在循环的情况下,循环变量只被'声明'一次.因此,循环中对循环变量的任何引用都将持续到下一次迭代.这包括列表推导中的变量.

  • @KeithIrwin,大多数允许关闭的语言都受到这种'gotchya'的影响.Javascript和C#是两个值得注意的例子.另外,OP从来没有提到关闭这个词,所以我想我会链接到解释它的材料,如果他们不知道的话. (4认同)