为什么map()和列表解析的结果不同? [英] Why results of map() and list comprehension are different?
问题描述
以下测试失败:
#!/ usr / bin / env python
def f ):
>>> t = 1,-1
>> f(* map(lambda i:lambda:i,t))
[1,-1]
>>> f(*(lambda:i for i in t))# - > [-1,-1]
[1 ,-1]
>>> f(* [lambda:i for i in t])# - > [-1,-1]
[1,-1] $ b
alist = [a()for a in args]
print(alist)
如果__name__ =='__main__':
import doctest ; doctest.testmod()
换句话说:
>>> t = 1,-1
>>> args = []
>>>> for i in t:
... args.append(lambda:i)
...
>>> map(lambda a:a(),args)
[-1,-1]
>>> args = []
>>> for i in t:
... args.append((lambda i:lambda:i)(i))
...
>>> map(lambda a:a(),args)
[1,-1]
>>> args = []
>>>> for i in t:
... args.append(lambda i = i:i)
...
>>> map(lambda a:a(),args)
[1,-1]
它们是不同的,因为生成器表达式和列表comp中的 i
的值是懒惰的,即当匿名函数在 f
中调用。
到那时, i
t
,这是-1。
所以基本上,这是列表推导所做的):
x = []
i = 1#1.从t
x.append :i)
i = -1#2.从t
x.append(lambda:i)
b $ b
现在lambdas继承一个引用 i
的闭包,但 i
绑定到-1
如果要确保lambda接收到的当前值, i
,do
f(* [lambda u = i:u for i in t]
这样,您强制执行 i
:生成器表达式和列表推导有一个区别:后者泄漏循环变量进入周围范围。
The following test fails:
#!/usr/bin/env python
def f(*args):
"""
>>> t = 1, -1
>>> f(*map(lambda i: lambda: i, t))
[1, -1]
>>> f(*(lambda: i for i in t)) # -> [-1, -1]
[1, -1]
>>> f(*[lambda: i for i in t]) # -> [-1, -1]
[1, -1]
"""
alist = [a() for a in args]
print(alist)
if __name__ == '__main__':
import doctest; doctest.testmod()
In other words:
>>> t = 1, -1
>>> args = []
>>> for i in t:
... args.append(lambda: i)
...
>>> map(lambda a: a(), args)
[-1, -1]
>>> args = []
>>> for i in t:
... args.append((lambda i: lambda: i)(i))
...
>>> map(lambda a: a(), args)
[1, -1]
>>> args = []
>>> for i in t:
... args.append(lambda i=i: i)
...
>>> map(lambda a: a(), args)
[1, -1]
They are different, because the value of i
in both the generator expression and the list comp are evaluated lazily, i.e. when the anonymous functions are invoked in f
.
By that time, i
is bound to the last value if t
, which is -1.
So basically, this is what the list comprehension does (likewise for the genexp):
x = []
i = 1 # 1. from t
x.append(lambda: i)
i = -1 # 2. from t
x.append(lambda: i)
Now the lambdas carry around a closure that references i
, but i
is bound to -1 in both cases, because that is the last value it was assigned to.
If you want to make sure that the lambda receives the current value of i
, do
f(*[lambda u=i: u for i in t])
This way, you force the evaluation of i
at the time the closure is created.
Edit: There is one difference between generator expressions and list comprehensions: the latter leak the loop variable into the surrounding scope.
这篇关于为什么map()和列表解析的结果不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!