2010-07-24 51 views
3

當發生器沒有完成數值並且讀取所有需要的結果時,是否有辦法停止屈服?我的意思是說,發電機在沒有做StopIteration的情況下給出數值。直到產生所有需要的值爲止,是否有辦法使切片變得很遲鈍

例如,這個從未停止:(修訂本)

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/

回答

0

這是最好的,我想到了,但它仍然切片兩次找的長度和需要從分割字符串轉換數爲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 

我將嘗試我的首要篩,但它可能不會比通過遞推公式計算長度算法更快。 Improving pure Python prime sieve by recurrence formula

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

正如你已經看到的,

TypeError: 'generator' object is unsubscriptable 

而且你寫devtrue的方式不應該停下來。如果你需要這種能力你可以:

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

或更爲簡單:

y = [True] * 5 

如果您無限發生器,它會產生無限。

+0

這不應該是不可能的,例如見/ dev/random pseudofile。除了stringIO之外,我們是否需要generatorIO軟件包? – 2010-07-24 12:23:47

+0

這不是不可能的。你寫了一個無限生成器,並得到你所要求的。我給了你一個我爲了清晰起見而簡化了的例子。 – msw 2010-07-24 12:39:55

+0

問題不是發電機,這是我想要的:發電機總是給出相同的價值。我只需要切片充當迭代器(列表是可迭代的),並在切片結束時執行StopIteration。 – 2010-07-24 13:43:03

0

與在Haskell的take功能類比,你可以建立基於另一個生成一個「有限的」發電機:

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 

您可以用「直到」生成器,「同時進一步這一想法」 ......

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

而且使用它像

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

...

+0

爲什麼使用自定義的take而不是islice?對我來說,一般增量就足夠了,自然數就是特殊情況,起始值爲0.如果生成器能夠訪問之前生成的值而不需要顯式設置變量和結果值(很像Python的命令行中的_變量) 。 – 2010-07-25 18:09:59

+0

@Tony Veijalainen:我可能誤讀了你的問題。我認爲你需要一種方法來限制生成結果的數量,而不管顯式地停止生成器。最重要的是,我還沒有深入瞭解itertools。感謝您指出了這一點! – xtofl 2010-07-26 06:46:32

+0

如果你有在Haskell的經驗,你也許可以教我一兩招。 – 2010-07-26 22:10:10

相關問題