Python 生成器,协程

生成器generator

    生成器可以简单有效的创建庞大的可迭代对象,而不需要在直接在内存中创建存储整个序列

        可以使用生成器推导式或者生成器函数来创建生成器

        生成器函数返回数据时使用yield语句,而不是使用return

>>> def countdown(n):
...     print("Counting down from %d" %n)
...     while n>0:
...             yield n
...             n -=1
...     return 'done'
...
>>> c = countdown(10)    #c为一个生成器对象

   

    可以通过next()函数或者生成器对象的__next__()方法来获得生成器的下一个返回值

    当计算到最后一个元素后,没有更多的元素时,抛出StopInteration,生成器终止

>>> c = countdown(3)
>>> next(c)
Counting down from 3
3
>>> c.__next__()
2
>>> next(c)
1
>>> next(c)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration: done

    通常直接通过for循环来迭代生成器,并且不需要关心StopInteration

    但是用for循环调用生成器时,发现拿不到生成器的return语句的返回值。

    如果想要拿到返回值,必须捕获StopInteration错误,返回值包含在StopInteration的value中

>>> while True:
...     try:
...         x = next(c)
...         print(c)
...     except StopIteration as e:
...         print('Generator return value:', e.value)
...         break
...

    当一个生成器没有全部迭代完成,但是不在使用了,可以调用close()方法关闭生成器,通常不必手动调用close()方法

c = countdown(10)
>>> next(c)
1
>>> c.close()
>>> next(c)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration


协程

         协程可以理解为就像生成器那样可以暂停的函数


    在函数内,当yield语句作为表达式使用,出现在赋值运算符的右边,在向函数发送值时函数将执行

    这种生成器函数可以被称为协程函数,而对协程函数的调用可以获得协程对象

"协程"一词可以用于协程函数和协程对象

>>> def coroutine():
...     print("Start Coroutine")
...     r = 'ok'
...     while True:
...             n = yield r
...             print('receiver %s' % n)
...
>>> c = coroutine()
>>> c.send(1)    
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't send non-None value to a just-started generator
>>> c.send(None)    #next(c)
Start Coroutine
'ok'
>>> c.send(1)
receiver 1
'ok'
>>> c.close()
>>> c.send(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

        在发送数据之前,应该调用c.send(None)启动生成器或者使用next()函数,使协程执行第一个yield之前的语句

        启动后协程会挂起,等待协程对象c的send()方法发送值

        yield语句会接收send()发送的值,并返回yield 语句后的值

        协程一般会不断执行下去,可以通过close()方法关闭协程


我们可以使用asyncio模块中的@asyncio.coroutine装饰器来使协程函数在调用时自动运行到yield语句前,而不需要提前调用send(None)或next()函数

具体的asyncio模块和协程的讲解可以看另一篇文章


  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值