Dla liczby 10**6 na moim sprzęcie bez jit'a.
next_test_pr (in sec): 0.03993 # 98.7257% faster than the slowest
lion_primes (in sec): 3.13345 # The slowest
def next_test(n=10**6):
if n < 100: return [i for i in (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) if i<n];
res = [2]; s = bytearray([0]); i = 3; j = 9;
nxt_i = lambda: i+2; nxt_j = lambda: i*i;
s *= n
def mo():
s[j::i+i] = bytearray([1])*int((n-(j))/(i+i)+1)
res.append(i)
while j<n:
mo() if not s[i] else None
i = nxt_i(); j = nxt_j();
return res + [g for g in range(i, n, 2) if not s[g]]
Co prawda można jeszcze szybciej z jeszcze mniejszym zużyciem pamięci wykorzystując cythona, ale to już powinno być wystarczająće, ale może ci posłuży mój algorytm ;p.
Najważniejsze tutaj to operować na fragmentach list, bo to potrafi ponad dziesięciokrotnie zoptymalizować program. (Srry za nie pythonowy zapis, ale na slajdzie musiało mi się zmieścić :)
@Edit: Takie wtrącenie co do sita euklidesa.
Na generator to łatwo przerobić, tylko wrzucasz inicjalizację w klasie dla wybranego przez siebie zakresu ;p.