python - 为什么 map() 和列表理解的结果不同?

标签 python closures list-comprehension late-binding generator-expression

<分区>

以下测试失败:

#!/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()

换句话说:

>>> 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 中调用匿名函数时。< br/> 届时,i 将绑定(bind)到 t 的最后一个值,即 -1。

所以基本上,这就是列表理解所做的(对于 genexp 也是如此):

x = []
i = 1 # 1. from t
x.append(lambda: i)
i = -1 # 2. from t
x.append(lambda: i)

现在 lambda 带有一个引用 i 的闭包,但是 i 在这两种情况下都绑定(bind)到 -1,因为这是它被分配的最后一个值。

如果你想确保 lambda 接收到 i 的当前值,做

f(*[lambda u=i: u for i in t])

这样,您可以在创建闭包时强制计算 i

编辑:生成器表达式和列表理解之间有一个区别:后者将循环变量泄漏到周围的范围中。

关于python - 为什么 map() 和列表理解的结果不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/139819/

相关文章:

javascript for 循环只给出元素的数量

python - 嵌套函数如何在 Python 中工作?

python - Python 的 heapify() 不能很好地处理列表理解和切片吗?

python - 创建重复N次的单项列表

Python 排列作为列表理解

python - 合并 pandas 中超过 50% 匹配的两个 df 列表字符串列表

python - 错误 : (gcloud. app.deploy) 错误响应:[9] Cloud build c90ad64e-2c2f-4ad0-a250-160de6f315df 状态:FAILURE

javascript - 如何在javascript中没有 promise 的情况下捕获闭包/ifffy函数内的错误

python - 加入两个 Pandas 数据框

python - 如何在 Python 中绘制显示不同类型商店类型总销售额的条形图?