Python中素数的生成器

时间:2012-11-15 02:58:28

标签: python

我尝试使用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,但这并不重要。了解会发生什么很重要。

3 个答案:

答案 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) )