加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python – 如何在生成器中检测到它已从外部中断

发布时间:2020-12-20 11:38:05 所属栏目:Python 来源:网络整理
导读:我有这个发电机: def gen(): rounds = 0 for x in xrange(10): rounds += 1 yield x print 'Generator finished (%d rounds)' % (rounds) 如果我称之为正常: for x in gen(): pass 我得到了预期的: Generator finished (10 rounds) 但如果我打断发电机,我
我有这个发电机:

def gen():
    rounds = 0
    for x in xrange(10):
        rounds += 1
        yield x
    print 'Generator finished (%d rounds)' % (rounds)

如果我称之为正常:

for x in gen():
    pass

我得到了预期的:

Generator finished (10 rounds)

但如果我打断发电机,我什么也得不到:

for x in gen():
    break

我想得到:

Generator interrupted (1 rounds)

是否有可能在发电机本身检测到它已从外部中断?是否有任何异常可以捕获以检测此事件?

解决方法

你不能,因为生成器的默认行为会一直被打断.每次生成一个值时,生成器都会不断暂停.

换句话说,您对生成器如何工作的理解是不正确的.发电机上的循环完全在发电机的控制之外;所有它的任务是产生一个下一个值,取消代码取消,直到执行下一个yield表达式.

因此,当没有请求下一个值时,生成器暂停并且不能执行代码以“检测”它没有被要求获得另一个值.

调用生成器函数时会发生什么:

>返回特殊的generator iterator object.函数体中没有代码被执行.
>生成器迭代器外部的代码可能会也可能不会将其用作迭代器.每次需要新值时,都会调用generator_object.next().
>调用.next()方法时,将运行函数体,直到遇到yield表达式.函数体被暂停,并且作为.next()方法的结果返回yield表达式的结果.

您可以使用generator_object.send()generator_object.throw()方法在生成器函数中显式发送消息或引发异常,但是在不迭代生成器对象时不会发送此类消息或异常.

您可以寻找的一件事是当生成器对象关闭时,GeneratorExit异常抛出生成器函数内部;见generator_object.close() method:

Raises a GeneratorExit at the point where the generator function was paused

当生成器对象被垃圾收集时(例如,没有任何引用它),将自动调用generator_object.close()方法:

def gen():
    rounds = 0
    for x in xrange(10):
        rounds += 1
        try:
            yield x
        except GeneratorExit:
            print 'Generator closed early after %d rounds' % rounds
            raise
    print 'Generator finished (%d rounds)' % rounds

演示:

>>> def gen():
...     rounds = 0
...     for x in xrange(10):
...         rounds += 1
...         try:
...             yield x
...         except GeneratorExit:
...             print 'Generator closed early after %d rounds' % rounds
...             raise
...     print 'Generator finished (%d rounds)' % rounds
... 
>>> for i in gen():
...     break
... 
Generator closed early after 1 rounds

这只能起作用,因为返回的生成器对象仅由for循环引用,并在for循环结束时获得.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读