这篇教程详解Python生成器和基于生成器的协程写得很实用,希望能帮到您。
一、什么是生成器Generator
1.生成器就是可以生成值的函数 2.当一个函数里有了 yield 关键字就成了生成器 3.生成器可以挂起执行并且保持当前执行的状态 代码示例: def simple_gen(): yield 'hello' yield 'world'gen = simple_gen()print(type(gen)) # 'generator' objectprint(next(gen)) # 'hello'print(next(gen)) # 'world'
二、基于生成器的协程Python3 之前没有原生协程,只有基于生成器的协程
1.pep 342(Coroutines via Enhanced Generators )增强生成器功能 2.生成器可能通过 yield 暂停执行和产出数据 3.同时支持send() 向生成器发送数据和throw() 向生成器抛出异常 Generator Based Corouteine代码示例: def coro(): hello = yield 'hello' # yield 关键字在 = 右边作为表达式,可以被 send 值 yield helloc = coro()# 输出 'hello', 这里调用 next 产出第一个值 'hello',之后函数暂停print(next(c))# 再次调用 send 发送值,此时 hello 变量赋值为 'world',然后 yield 产出 hello 变量的值 'world'print(c.send('world'))# 之后协程结束,后续再 send 值会抛出异常 StopIteration 运行结果: 
三、协程的注意点协程注意点 1.协程需要使用send(None) 或者next(coroutine) 来预激(prime )才能启动 2.在yield 处协程会暂停执行 3.单独的yield value 会产出值给调用方 4.可以通过 coroutine.send(value) 来给协程发送值,发送的值会赋值给 yield 表达式左边的变量value = yield 5.协程执行完成后(没有遇到下一个yield 语句)会抛出StopIteration 异常
四、协程装饰器避免每次都要用 send 预激它 from functools import wrapsdef coroutine(func): # 这样就不用每次都用 send(None) 启动了 “”“装饰器:向前执行到一个 `yield` 表达式,预激 `func` ”“” @wrops(func) def primer(*args, **kwargs): # 1 gen = func(*args, **kwargs) # 2 next(gen) # 3 return gen # 4 return primer
五、python3原生协程python3.5引入 async/await支持原生协程(native coroutine) import asyncioimport datetimeimport randomasync def display_date(num, loop): end_time = loop.time() + 50.0 while True: print('Loop: {} Time: {}'.format(num, datetime.datetime.now()) if (loop.time() + 1.0) >= end_time: break await asyncio.sleep(random.randint(0, 5))loop = asyncio.get_event_loop()asyncio.ensure_future(display_date(1, loop))asyncio.ensure_future(display_date(2, loop))loop.run_forever() 到此这篇关于详解Python生成器和基于生成器的协程的文章就介绍到这了,更多相关Python生成器与协程内容请搜索51zixue.net以前的文章或继续浏览下面的相关文章希望大家以后多多支持51zixue.net! Python模拟登录网易云音乐并自动签到 使用numpy实现矩阵的翻转(flip)与旋转 |