直到所有需要的值都产生为止,有没有办法让切片变得懒惰

发布于 2024-09-11 02:29:38 字数 515 浏览 4 评论 0原文

当生成器未完成值并且所有需要的结果已被读取时,是否有方法停止生成?我的意思是生成器在不执行 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 -递归生成器函数/

Is there way to stop yielding when generator did not finish values and all needed results have been read? I mean that generator is giving values without ever doing StopIteration.

For example, this never stops: (REVISED)

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

I found this code, but do not yet understand, how to apply it in this case:
http://code.activestate.com/recipes/576585-lazy-recursive-generator-function/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

鲜血染红嫁衣 2024-09-18 02:29:38

您可以在生成器对象上调用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

You can call close() on the generator object. This way, a GeneratorExit exception is raised within the generator and further calls to its next() method will raise 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
神也荒唐 2024-09-18 02:29:38

正如您已经看到的,

TypeError: 'generator' object is unsubscriptable

并且您编写 devtrue 的方式不应该停止。如果你需要这种能力,你可以:

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

或者更简单地说:

y = [True] * 5

如果你制造一个无限的发电机,它将无限地产生。

As you have already seen,

TypeError: 'generator' object is unsubscriptable

And the way you have written devtrue it shouldn't stop. If you need that capacity you could:

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

or far more simply:

y = [True] * 5

If you make an infinite generator, it will generate infinitely.

享受孤独 2024-09-18 02:29:38

与 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

您可以使用“until”生成器、“while”等进一步扩展这个想法

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

像...

In analogy with the take function in Haskell, you can build a 'limited' generator based upon another generator:

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

You can further this idea with an "until" generator, a "while", ...

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

And use it like

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

...

心如狂蝶 2024-09-18 02:29:38

这是我想出的最好的方法,但它仍然会进行两次切片以找到长度,并且需要将字符串号从分割转换为整数:

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素数筛

This is best I came up with, but it does still the slicing twice to find the length and need to convert string number from splitting to 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

I will try it to my prime sieve, but it is likely not to be faster than doing the length arithmetic from recurrence formula.
Improving pure Python prime sieve by recurrence formula

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文