生成器
生成器generator
- 生成器指的是生成器对象,可以由生成器表达式得到,也可以使用yield关键字得到一个生成器函数,调用这个函数得到一个生成器对象
生成器函数
- 函数体中包含yield语句的函数,返回生成器对象
- 生成器对象,是一个可迭代对象,是一个迭代器
- 生成器对象,是延迟计算、惰性求值的
示例:
In [2]: def inc():...: for i in range(5):...: yield i...:...: print(type(inc))...: print(type(inc()))...: x = inc()...: print(type(x))...: print(next(x))...:...: for m in x:...: print(m, '*')...:<class 'function'><class 'generator'><class 'generator'>01 *2 *3 *4 *
- yeild语句返回的结果不在是一个值,而是一个generator对象
- 生成器函数需要通过next()的方式来获取值
- 也可以使用for循环获取,生成器对象迭代走完一遍后不可再次迭代
生成器总结
- 生成器函数的函数体不会立即执行,必须调用后生成一个生成器
- 在生成器函数中,可以使用多个yield语句,使用next(generator)执行一次会暂停执行,把yeild值返回
- 再次执行会执行到下一次yield语句
- return语句依然可以终止函数运行,但return语句的返回值不能被获取的到
- return会导致无法继续获取下一个值,跑出StopIteration异常
- 如果函数没有显示的return语句,如果生成器函数执行到结尾,一样会跑出StopIteration异常
- 如不想出现异常,可使用传入默认值的方式,如:next(g, ‘’End”)
协程coroutine
- 生成的高级用法
- 比进程、协程轻量级
- 是在用户空间调度函数的一种实现
- Python3 asyncio就是协程实现,已经加入到了标准库
- python 3.5使用async、 await关键字直接原生支持协程
协程调度的实现思路
- 有2个生成器A和B
- next(A)后,A执行到了yield语句暂停,然后去执行next(B),B执行到yield语句也暂停,然后再次调用next(A),再调用next(B),周而复始,就实现了调度的效果。
- 可以引入调度的策略来实现切换的方式
- 协程是一种非抢占式调度。
yeild from
- 简化yeild代码的语法糖
- 示例
def inc():
for x in range(1000):
yeild x
# 上述代码等同于:
def inc():
yeild from range(1000)
