在Python中创建一个简单的主筛

时间:2015-03-11 18:32:41

标签: python

我使用Python编写了一个简单的主筛(Eratosthenes的无界筛子),但由于某种原因,它无法正常工作。这是筛子:

from itertools import count

def sieve():
    nums = count(2)
    while True:
        n = next(nums)
        nums = filter(lambda k: k%n != 0, nums)
        yield n

不幸的是,这不起作用。相反,它只返回与count(2)迭代器相同的值。

为了比较,这个:

nums = count(2)
print(next(nums))
nums = filter(lambda k: k%2 != 0, nums)
print(next(nums))
nums = filter(lambda k: k%2 != 0, nums)
print(next(nums))

将打印:

2
3
5

筛选功能将打印出来:

2    3    4

我认为问题在于Python的lambda的奇怪行为,但是替换了这一行:

nums = filter(lambda k: k%n != 0, nums)

使用:

def f(k): return k%n != 0
nums = filter(f, nums)

无法解决问题。

1 个答案:

答案 0 :(得分:7)

问题在于lambda始终引用n最新值,而不是lambda创建时使用的值。最简单的方法是使用关键字参数显式捕获值:

from itertools import count

def sieve():
    nums = count(2)
    while True:
        n = next(nums)
        nums = filter(lambda k, n=n: k%n != 0, nums)
        yield n

此Python问题在well-documented StackOverflow various中为answers。公平地说,其他一些具有词汇闭包的语言也会共享相同的行为,例如JavaScriptCommon Lisp

这可能是你所说的" Python lambda"的奇怪行为。在这个问题中,虽然这种行为与lambda无关,但是当引用一个可变变量时,闭包真正捕获了什么 - 在Python,JavaScript和Common Lisp中,它捕获变量的最新值,而在Scheme它捕获变量的值,就像创建闭包时一样。