Sco*_*ork 1 python lambda filter
要了解lambdas,我正在学习本教程,并遇到了关于计算素数的例子(python 2.x):
nums = range(2,50)
for i in range(2,8):
nums = filter(lambda x: x == i or x % i, nums)
print (list(nums))
Run Code Online (Sandbox Code Playgroud)
版画
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
Run Code Online (Sandbox Code Playgroud)
但是,在python 3.4中尝试这个时,它产生了意想不到的行为:
nums = range(2,50)
for i in range(2,8):
nums = filter(lambda x: x == i or x % i , nums)
print(list(nums))
Run Code Online (Sandbox Code Playgroud)
版画
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 43, 44, 45, 46, 47, 48]
Run Code Online (Sandbox Code Playgroud)
我不明白为什么会有区别.我知道过滤器在python 3(而不是列表)中返回一个过滤器对象,但据我所知,这不应该影响结果.
删除for循环会产生正确的结果:
>>> nums = range(2,50)
>>> nums = filter(lambda x: x == 2 or x % 2, nums)
>>> nums = filter(lambda x: x == 3 or x % 3, nums)
>>> nums = filter(lambda x: x == 4 or x % 4, nums)
>>> nums = filter(lambda x: x == 5 or x % 5, nums)
>>> nums = filter(lambda x: x == 6 or x % 6, nums)
>>> nums = filter(lambda x: x == 7 or x % 7, nums)
>>> print(list(nums))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
Run Code Online (Sandbox Code Playgroud)
我希望有人可以启发我,因为我很好奇正在发生的事情.
这种行为是两件事的结合.一个是,在Python 3中,filter
(和range
)返回一次产生一个值的对象,而不是预先计算所有值.另一个是,在Python 2和3中,引用封闭范围中的名称的函数会创建对名称的闭包,而不是值.
在Python 3版本中,在每次循环迭代中,使用函数(lambda)创建过滤器.因为过滤器是"懒惰的",所以只要您要求过滤值,它就会存储该函数并稍后调用它.(在这种情况下,当你调用时list(nums)
.)但是该函数引用i
了函数外部的变量.因此,当filter
调用该函数时,它会i
在您获得过滤值(即调用时list(nums)
)时使用该值调用它,而不是在创建过滤器时调用它.这就是为什么你的结果缺少7的所有倍数(7除外):7是你i
循环中的最后一个值,所以你所有的lambdas都会在它们被调用时检查7的倍数.
重现Python 2行为的一种方法,正如Bhargav Rao在评论中所说,是将你的lambda改为过滤list(nums)
而不是nums
.这会强制每个过滤器"清除"前一个过滤器,而不是等到最后应用它们.(这实际上是Python 2所做的,这就是为什么你在Python 2中没有看到这种行为的原因.)
另一种方法是使用关于闭包的链接问题中描述的默认参数技巧.将循环体更改为:
nums = filter(lambda x, i=i: x == i or x % i , list(nums))
Run Code Online (Sandbox Code Playgroud)
使i
lambda的参数"锁定"每个循环迭代的值.这意味着过滤器仍然会延迟运行,但每个过滤器都会存储适当的值以进行过滤,因此即使稍后调用它(更改后i
),它仍然可以工作.
归档时间: |
|
查看次数: |
90 次 |
最近记录: |