Just playing around with various ways of generating prime numbers. The focus is on readability, not speed.


In [1]:
from itertools import islice, count

In [2]:
known_good_primes = [2, 3, 5, 7, 11, 13, 17,19, 23, 29]

In [3]:
def check():
    assert list(islice(gen_primes(), len(known_good_primes))) == known_good_primes

In [4]:
def gen_primes(start=2):
    for p in count(start):
        for divisor in range(2, p):
            if p % divisor == 0:
                break
        else:
            yield p

In [5]:
check()

In [6]:
def is_divisible(p):
    return any(p % divisor == 0 for divisor in range(2, p))

def gen_primes(start=2):
    return (
        p
        for p in count(start)
        if not is_divisible(p)
    )

In [7]:
check()

In [8]:
def is_prime(p):
    return all(p % divisor != 0 for divisor in range(2, p))

def gen_primes(start=2):
    return (p for p in count(start) if is_prime(p))

In [9]:
check()

This is pretty readable.


In [10]:
def is_prime(p):
    return all(p % divisor != 0 for divisor in range(2, p))

def gen_primes(start=2):
    return filter(is_prime, count(start))

In [11]:
check()

Do it all in one expression. It works, but is ugly and hard to read.


In [12]:
def gen_primes(start=2):
    return filter(
        lambda p: all(p % divisor != 0 for divisor in range(2, p)),
        count(start)
    )

In [13]:
check()