如何使切片变得惰性,以便在所有需要的值被生成之前保持生成?
有没有办法让生成器在没有完成所有值时停止输出,而是当我们已经读取了所有需要的结果时就停止?我的意思是,这个生成器一直在输出值,却从来没有发出停止的信号。
比如,下面这个例子是永远不会停止的:(已修订)
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素数筛算法