如何使切片变得惰性,以便在所有需要的值被生成之前保持生成?

3 投票
4 回答
576 浏览
提问于 2025-04-16 01:46

有没有办法让生成器在没有完成所有值时停止输出,而是当我们已经读取了所有需要的结果时就停止?我的意思是,这个生成器一直在输出值,却从来没有发出停止的信号。

比如,下面这个例子是永远不会停止的:(已修订)

from random import randint
def devtrue():
    while True:
        yield True

answers=[False for _ in range(randint(100,100000))]
answers[::randint(3,19)]=devtrue()
print answers

我找到了一段代码,但还不太明白怎么在这种情况下使用它:http://code.activestate.com/recipes/576585-lazy-recursive-generator-function/

4 个回答

0

正如你已经看到的,

TypeError: 'generator' object is unsubscriptable

你写的 devtrue 这样是不会停止的。如果你需要这样的功能,你可以:

def bounded_true(count)
   while count > 0:
       yield True
       count -= 1

或者更简单的方法是:

y = [True] * 5

如果你创建一个无限生成器,它会一直生成下去。

8

你可以在生成器对象上调用 close() 方法。这样一来,生成器内部会抛出一个 GeneratorExit 异常,之后再调用它的 next() 方法时,就会抛出 StopIteration 异常:

>>> def test():
...     while True:
...         yield True
... 
>>> gen = test()
>>> gen
<generator object test at ...>
>>> gen.next()
True
>>> gen.close()
>>> gen.next()
Traceback (most recent call last):
  ...
StopIteration
0

这是我想到的最好办法,但它还是需要两次切片来找长度,并且需要把分割出来的字符串数字转换成整数:

from time import clock
from random import randint
a=[True for _ in range(randint(1000000,10000000))]
spacing=randint(3,101)
t=clock()
try:
    a[::spacing]=[False]
except ValueError as e:
    a[::spacing]=[False]*int(e.message.rsplit(' ',1)[-1])

print spacing,clock()-t

# baseline

t=clock()
a[::spacing]=[False]*len(a[::spacing])
print 'Baseline:',spacing,clock()-t

我会把它试用在我的素数筛算法上,但可能没有通过递归公式来做长度计算更快。通过递归公式改进纯Python素数筛算法

撰写回答