我想做点什么
>>> lst = [1, 2]
>>> i = iter(lst)
>>> next(i)
1
>>> next(i)
2
>>> next(i)
Traceback (most recent call last): StopIteration
>>> lst.append(3) #
# append some more values
>>> lst.append(4) #
>>> next(i) # !!!
3 # this does not work in Python 3.4;
# I get StopIteration again
上下文:我正在编写一些分解代码;如果我用完存储的素数进行测试,我想找到更多,然后继续我离开的地方。
更具体地说,我想做一些像
这样的事情n = 600851475143933 # number to factorize
factors = []
primes = [2, 3, 5, 7, 11] # currently contains about 850,000 primes;
# I'd like not to restart from the beginning
# each time.
p_iter = iter(primes)
while True:
try:
p = next(p_iter)
# fully factored?
if p*p > n:
if n > 1:
factors.append(n)
break
# pull out as many p's as possible
while not(n % p):
factors.append(p)
n //= p
except StopIteration:
append_more_primes(primes)
# and continue where I left off
但是我想我必须编写一个内部处理这个问题的无限素数序列生成器; yield from primes
然后在我追加它们时产生新的素数。
如何在保持快速的同时干净利落地做任何其他建议?
答案 0 :(得分:0)
你并不是一直需要整个清单。你只需附加到右端并从左侧弹出。所以使用
primes.append(elem)
和
elem = primes.pop(0)
这里是你的代码:
while True:
if not primes:
append_more_primes(primes)
p = primes.pop(0)
# ... your code
您也可以使用collections.deque。
答案 1 :(得分:0)
这是怎么做的。我已经稍微改变了这个问题,所以你正在寻找均衡而不是素数,因为我只是更容易进行测试,看看是否有问题。
def provide_evens():
i = 0
while True:
if i%2 == 0:
yield i
i+=1
for next_even in provide_evens():
print next_even
if next_even>10:
break
输出是:
0
2
4
6
8
10
12
对于你的问题,在每次收益之后,你需要以某种方式得到下一个素数。
答案 2 :(得分:0)
对于那些感兴趣的人,这里是我最终得到的(最相关的位是.infinite_sequence
方法)。
from bisect import bisect_left
from functools import reduce
from operator import mul
def product_(lst):
return reduce(mul, lst)
class Primes:
def __init__(self, n):
"""
Use a modular sieve based on the first n primes
"""
self.primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
self.upto = 30
assert 1 < n < len(self.primes)
self.basis, self.primes = self.primes[:n], self.primes[n:]
self.wheel_size = ws = product_(self.basis)
self.wheel = [i - ws for i in range(ws, ws * 2) if all(i % b for b in self.basis)]
self.wheel_set = set(self.wheel)
# complete all primes <= wheel_size
if self.upto < ws:
for i in self.wheel:
if i > self.upto:
for p in self.primes:
if p*p > i:
self.primes.append(i)
break
elif not(i % p):
break
self.upto = ws
# from now on, self.upto must always be a multiple of wheel_size
assert self.upto % ws == 0
def __iter__(self):
return self.infinite_sequence()
def infinite_sequence(self, include_basis=True):
"""
Yield an infinite sequence of prime numbers
"""
primes = self.primes
ws = self.wheel_size
wheel = self.wheel
# start with the primes we already have stored
if include_basis:
yield from self.basis
yield from primes
# infinite loop
while True:
# calculate next block of primes
new_primes = []
upto = self.upto
for w in wheel: # automatically excludes basis primes
i = upto + w # next candidate
for p in primes: # test factors
if p*p > i:
# new prime found
new_primes.append(i)
break
elif not(i % p):
# found a factor - not prime
break
# copy back to stored primes
primes.extend(new_primes)
self.upto += ws
# and yield new values
yield from new_primes
def is_prime(self, n):
if n <= self.upto:
# must be in already-found primes
return self.primes[bisect_left(self.primes, n)] == n
else:
# test against basis primes
if (n % self.wheel_size) not in self.wheel_set:
return False
else:
# test possible prime factors
for p in self.infinite_sequence(False):
if p*p > n:
return True
elif not(n % p):
return False
def factorize(self, n):
factors = []
for p in self:
if p*p > n:
if n > 1:
factors.append(n)
return factors
while not(n % p):
# pull out all factors of p
factors.append(p)
n //= p
primes = Primes(5)