Rindiendo hasta que se obtengan todos los valores necesarios, ¿hay alguna manera de hacer que la división se vuelva perezosa?

¿Hay alguna forma de dejar de rendir cuando el generador no terminó los valores y se leyeron todos los resultados necesarios? Quiero decir que el generador está dando valores sin hacer StopIteration.

Por ejemplo, esto nunca se detiene: (REVISADO)

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 

Encontré este código, pero aún no lo entiendo, cómo aplicarlo en este caso: http://code.activestate.com/recipes/576585-lazy-recursive-generator-function/

Puede llamar a close() en el objeto generador. De esta manera, se StopIteration una excepción de GeneratorExit dentro del generador y las llamadas posteriores a su método next() generarán StopIteration :

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

Como ya has visto,

 TypeError: 'generator' object is unsubscriptable 

Y la forma en que ha escrito devtrue no debería detenerse. Si necesita esa capacidad usted podría:

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

o mucho más simple:

 y = [True] * 5 

Si haces un generador infinito, se generará infinitamente.

En analogía con la función de take en Haskell, puede construir un generador ‘limitado’ basado en otro generador:

 def take(n,gen): '''borrowed concept from functional languages''' togo=n while togo > 0: yield gen.next() togo = togo - 1 def naturalnumbers(): ''' an unlimited series of numbers ''' i=0 while True: yield i i=i+1 for n in take(10, naturalnumbers() ): print n 

Puedes promover esta idea con un generador de “hasta”, un “tiempo”, …

 def gen_until( condition, gen ): g=gen.next() while( not condition(g) ): yield g g=gen.next() 

Y usalo como

 for i in gen_until( lambda x: x*x>100, naturalnumbers() ): print i 

Esto es lo mejor que se me ocurrió, pero sigue cortando dos veces para encontrar la longitud y la necesidad de convertir el número de cadena de división a int:

 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 

Lo intentaré en mi primer tamiz, pero es probable que no sea más rápido que la aritmética de longitud de la fórmula de recurrencia. Mejora de la criba pura de Python prime por fórmula de recurrencia