Here is my code:
def odd_numbers_from(n):
if n % 2 == 0:
n = n + 1
while True:
yield n
n = n + 2
def takeWhile(pred, lst):
for item in lst:
if pred(item):
yield item
else:
break
def takePrimes(iterator):
for n in iterator:
if not 0 in (n % k for k in takeWhile(lambda x: x**2 <= n, primes())):
yield n
# -- memoized prime generator
def primes(earlier_primes=[2]):
yield from earlier_primes
for new_prime in takePrimes(odd_numbers_from(earlier_primes[-1]+1)):
earlier_primes.append(new_prime)
yield new_prime
if __name__ == "__main__":
for k in primes():
print(k)
if k > 300:
break
In first run, it will produce prime numbers as long as they are requested. On subsequent runs, it will just yield from previously generated primes. We can test this behaviour like this:
# -- memoized prime generator
def primes(earlier_primes=[2]):
yield from earlier_primes
for new_prime in takePrimes(odd_numbers_from(earlier_primes[-1]+1)):
print("generated new prime")
earlier_primes.append(new_prime)
yield new_prime
if __name__ == "__main__":
for k in primes():
print(k)
if k > 20:
break
print("=====")
for k in primes():
print(k)
if k > 30:
break
This should output:
2
generated new prime
3
generated new prime
5
generated new prime
7
generated new prime
11
generated new prime
13
generated new prime
17
generated new prime
19
generated new prime
23
=====
2
3
5
7
11
13
17
19
23
generated new prime
29
generated new prime
31
How does it look?