列表推导中的Lambda [英] Lambdas inside list comprehensions

查看:58
本文介绍了列表推导中的Lambda的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个lambda列表,它们充当某种繁重计算的缓存,并注意到了这一点:

I wanted to have a list of lambdas that act as sort of a cache to some heavy computation and noticed this:

>>> [j() for j in [lambda:i for i in range(10)]]
[9, 9, 9, 9, 9, 9, 9, 9, 9, 9]

尽管

>>> 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>]

意思是lambda是唯一的函数,但是它们都以某种方式共享相同的索引值.

Meaning that the lambdas are unique functions but they somehow all share the same index value.

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

Is this a bug or a feature? How do I avoid this problem? It's not limited to list comprehensions...

>>> 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]

推荐答案

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

The lambda returns the value of i at the time you call it. Since you call the lambda after the loop has finished running, the value of i will always be 9.

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

You can create a local i variable in the lambda to hold the value at the time the lambda was defined:

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

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

Another solution is to create a function that returns the 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]

之所以起作用,是因为为每个create_lambda调用创建了一个不同的闭包(持有不同的i值).

This works because there is a different closure (holding a different value of i) created for each invocation of create_lambda.

这篇关于列表推导中的Lambda的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆