我在玩Python生成器和itertools模块,并尝试制作无限版的Eratosthenes筛。这是我的代码:
itertools
from itertools import count, ifilter, islice def sieve_broken(): candidates = count(start=2) while True: prime = next(candidates) yield prime candidates = ifilter(lambda n: n % prime, candidates)
当我对其进行测试时,我得到以下信息:
>>> print list(islice(sieve_broken(), 10)) [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
但是,如果我用candidates这样的函数代替的重新分配:
candidates
def sieve_fixed(): def exclude_multiples(factor, numbers): return ifilter(lambda n: n % factor, numbers) candidates = count(start=2) while True: prime = next(candidates) yield prime candidates = exclude_multiples(prime, candidates)
我得到:
>>> print list(islice(sieve_fixed(), 10)) [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
我不知道为什么第一个版本不起作用。据我所知,这两个版本应该等效。有谁知道为什么他们不一样?
在Python中使用闭包时,您已经陷入了一个非常普遍的陷阱:闭包具有其作用域,并且您会在同一范围内继续替换值。
candidates = ifilter(lambda n, prime=prime: n % prime, candidates)