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
.
你在这里看到的是封闭的影响.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)
最后,在循环的情况下,循环变量只被'声明'一次.因此,循环中对循环变量的任何引用都将持续到下一次迭代.这包括列表推导中的变量.
归档时间: |
|
查看次数: |
725 次 |
最近记录: |