我尝试使用Eratosthenes的steve在Python中创建所有素数的流。但是,我收到了一个错误。
以下是我的尝试:
def genPrimes0(N):
if (isPrime(N)):
yield [N]
filter(lambda x: N%x[0] == 0, genPrimes0(N+1))
else:
genPrimes0(N+1)
P = genPrimes0(2)
这是控制台:
>>> ================================ RESTART ================================
>>>
>>> P.next()
[2]
>>> P.next()
Traceback (most recent call last):
File "<pyshell#10>", line 1, in <module>
P.next()
StopIteration
>>>
有什么想法吗?
编辑:
我想要递归。我想用LAZY评估做一个实验。特别是对这个问题不感兴趣,但关于懒惰的评估 - 我完全随机地选择了这个问题来进行实验。
我正在使用带有Idle的Python 2.7,但这并不重要。了解会发生什么很重要。
答案 0 :(得分:6)
我认为你在当前的发电机上做得太费力了。你可以减少工作量(例如拥有isPrime
oracle)并让算法做它的事情:
def primes(n=2): # don't provide a different n value, or you will get odd results
yield n
yield from filter(lambda x: x % n, primes(n+1))
它使用了一些Python 3.3特定的语法(yield from
),但你可以为早期版本做一个等效的生成器,只需使它成为过滤器结果的显式循环。 @ icktoofay的答案显示了这种循环(他还指出filter
只是Python 3中的一个生成器,所以如果你使用的是Python 2,请使用itertools.ifilter
。
示例输出:
>>> for p in primes():
print(p)
if p > 100:
break
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
101
答案 1 :(得分:4)
您不需要递归进行延迟评估,您可以使用itertools中的函数来懒惰地计算素数。
import itertools
def primes():
numbers = itertools.count(2)
while True:
p = numbers.next()
numbers = itertools.ifilter(lambda x, p=p: x%p, numbers)
yield p
print list(itertools.islice(primes(), 100))
答案 2 :(得分:2)
这不是Eratosthenes,而是仅使用填充堆栈的非尾递归函数。如果你有isPrime函数,你应该写如
def gen_primes(start):
return itertools.filter(isPrime , itertools.count(start) )