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

发布于 2021-01-29 19:34:14

以下测试失败:

#!/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]
关注者
0
被浏览
58
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    它们是不同的,因为i生成器表达式和list comp中的值都是惰性计算的,即在中调用匿名函数时f
    到那时,i如果绑定到最后一个值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在两种情况下均绑定为-1,因为这是为其分配的最后一个值。

    如果要确保lambda接收到的当前值i,请执行

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

    这样,您i可以在创建闭包时强制进行评估。

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



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看