在StopIteration之后通过向列表添加项目来继续iter(list)的任何方法?

时间:2015-01-27 05:38:18

标签: python iterator

我想做点什么

>>> 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然后在我追加它们时产生新的素数。

如何在保持快速的同时干净利落地做任何其他建议?

3 个答案:

答案 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)