有人可以帮助我理解为什么实现“Eratosthenes筛”的以下代码在
Python 2和
Python 3中表现不同.
l = range(2,20) for i in range(2,6): l = filter(lambda x: x == i or x % i != 0,l) print(tuple(l))
使用Python 2.7:
> python filter.py (2,3,5,7,11,13,17,19)
使用Python 3.6:
> python filter.py (2,4,6,8,9,12,14,16,18,19)
解决方法
这里有两个部分发挥作用:
>在python-3.x中,过滤器用作生成器:过滤是懒惰的;和
> lambda x中的i:…更新以及for循环中的i进行更新.
所以最后你所构建的是:
l = filter(lambda x: x == 5 or x % 5 != 0,filter(lambda x: x == 5 or x % 5 != 0,l) ) ) )
请注意,所有过滤都像我一直是5一样完成.所以现在你调用元组(..),实际的过滤将被完成,正如你所看到的,只有五个不是五个自身的多个被过滤掉了.
一个简单的解决方法是在循环中使用list,以便主动完成过滤:
l = range(2,6): l = list(filter(lambda x: x == i or x % i != 0,l)) print(tuple(l))
在python中运行它返回:
>>> l = range(2,20) >>> for i in range(2,6): ... l = list(filter(lambda x: x == i or x % i != 0,l)) ... >>> print(l) [2,19]
请注意,虽然python-2.7和python-3.x看起来完全相同,但实际上这些“不同”的语言彼此不兼容:运行在一个中的代码并不总是在另一个中起作用,反之亦然.
另一个注释(@ShadowRanger的信用)是一个实际上可以绑定你的lambda.您可以通过创建“高阶lambda”来完成此操作.而不是写:
lambda x : x == i or x % i != 0
你写:
(lambda j : (lambda x : x == j or x % j != 0))(i)