从迭代器外部发送StopIteration for循环 [英] Sending StopIteration to for loop from outside of the iterator

查看:162
本文介绍了从迭代器外部发送StopIteration for循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



它们是:

1)在xrange(10)中使用break-continue

 
在xrange(10)中使用y:
print x * y
if x * y> 50:
break
else:
continue#只有当break不被使用时才执行
break



2)使用返回

  def foo():
for x在范围(10)中:
在范围(10)中为y:
print x * y
if x * y> 50:
return
foo()



3)使用特殊的异常


  class BreakIt(Exception):pass 

try:
):
在范围(10)中为y:
print x * y
if x * y> 50:
提高BreakIt
除了BreakIt:
传递

I有一些想法,可以有其他的方式来做到这一点。
通过使用直接发送到外部循环的StopIteration异常。
我写了这段代码

$ $ $ $ $ b $ it $($)
为范围内的j(10):
if i * j == 20:
提升StopIteration

不幸的是,StopIteration没有被任何for循环所捕获,并且代码产生了一个丑陋的Traceback。
我认为这是因为StopIteration不是从迭代器 it 内发送的。 (这是我的猜测,我不确定)。

有什么方法可以将StopIteration发送到外部循环?



感谢!

解决方案

您可以使用协程来做这样的事情:
$ b

  def stoppable_iter(可迭代):
it iter(可迭代)
for v:
x = yield v
if x:
yield
return

然后使用它像这样:

  it = stoppable_iter(范围(10))
for i:
for j在范围内(10):
打印i,j
如果i * j == 20:
it.send(StopIteration)#或任何值为真的
中断

以下是一个简单的例子:

 >>> t = stoppable_iter(范围(10))
>>> t.next()
0
>>> t.next()
1
>>> t.send(StopIteration)
>>> t.next()
Traceback(最近一次调用的最后一个):
在< module>中,第1行的文件< stdin>
StopIteration


There are several ways to break out of a few nested loops

They are:

1) to use break-continue

for x in xrange(10):
    for y in xrange(10):
        print x*y
        if x*y > 50:
            break
    else:
        continue  # only executed if break was not used
    break

2) to use return

def foo():
    for x in range(10):
        for y in range(10):
            print x*y
            if x*y > 50:
                return
foo()

3) to use special exception

class BreakIt(Exception): pass

try:
    for x in range(10):
        for y in range(10):
            print x*y
            if x*y > 50:
                raise BreakIt
except BreakIt:
    pass

I had some thought that there could be some other way to do it. It is by using StopIteration exception sent directly to the outer loop. I wrote this code

it = iter(range(10))
for i in it:
    for j in range(10):
        if i*j == 20:
            raise StopIteration

Unfortunately, StopIteration hadn't been caught by any for-loop and that code produced an ugly Traceback. I think it's because StopIteration wasn't sent from inside of iterator it. (that's my guess, I'm not sure about it).

Is there any way that I can send StopIteration to the outer loop?

Thanks!

解决方案

You can do something like this with coroutines:

def stoppable_iter(iterable):
    it = iter(iterable)
    for v in it:
        x = yield v
        if x:
            yield
            return

And then use it like this:

it = stoppable_iter(range(10))
for i in it:
    for j in range(10):
        print i, j
        if i*j == 20:
            it.send(StopIteration) # or any value that evaluates as True
            break

And a brief example of how it works:

>>> t = stoppable_iter(range(10))
>>> t.next()
0
>>> t.next()
1
>>> t.send(StopIteration)
>>> t.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

这篇关于从迭代器外部发送StopIteration for循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆