Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is this primes generator pythonic

Is the following code for generating primes pythonic?

def get_primes(n):
    primes=[False,False]+[True]*(n-1)
    next_p=(i for i,j in enumerate(primes) if j)
    while True:
        p=next(next_p)
        yield p
        primes[p*p::p]=[False]*((n-p*p)//p+1)

Note that next(next_p) will eventually throw a StopIteration error which somehow ends the function get_primes. Is that bad?

Also note that next_p is a generator which iterates over primes, however primes changes during iteration. Is that bad style?

adding the following if statement gets it under 0.25 seconds for the first million primes:

if p*p<=n:
    primes[p*p::p]=[False]*((n-p*p)//p+1)
like image 248
robert king Avatar asked Feb 15 '12 03:02

robert king


1 Answers

It's not bad that next(next_p) throws a StopIteration error -- that's what a generator always does when it runs out of items!

Changing the length of a list while iterating over it is a bad idea. But there's nothing wrong with simply changing the contents. Overall, I think this is a rather elegant, if basic, seive.

One small observation: when you "cross out" the multiples of prime numbers, you'll find, if you think about it for a bit, that you don't have to start with p * 2. You can skip ahead to p ** 2.

like image 86
senderle Avatar answered Sep 30 '22 09:09

senderle