创建生成器

  创建生成器需要两部步骤

  1. 定义一个包含yield语句的函数
  2. 调用第一步创建的函数得到生成器
def test(val,step):
2 print("函数开始执行")
3 cur = 0
4 for i in range(val):
5 cur += i * step
6 yield cur
7

yeild cur 语句的两个作用:

  1. 每次返回一个值,有点类似与return语句
  2. 冻结执行,程序每次执行到yield语句时就会停止运行

在程序被冻结时,当程序调用next()函数获取生成器的下一个值时,程序才会继续向下执行

需要注意的是,当程序调用含yeild的函数时,并不会立即执行,它只是返回一个生成器。

if __name__ == "__main__":
9 #此时程序并不会立即运行
10 t = test(10,2)
11 #获取生成器的第一个值
12 print(next(t))#生成器被冻结在yield处
13 print(next(t))

运行结果:

函数开始执行
0
2
从运行结果可以看出,当程序执行 t = test(10,2)时,程序并没有开始执行test()函数,当程序第一次调用next(t)时,test()函数才开始执行。当程序调用next(t)时,生成器会返回yield cur 语句返回的值,程序被冻结在yield语句处,所以可以看到生成器第一次输出的值是0

当程序第二次调用next(t),程序的“冻结”被解除,继续向下执行。

程序可以用for循环来遍历生成器,相当于不断的使用next()函数来获取生成器的值。

for ele in t:
print(ele,end = "\t")

程序运行结果

6       12      20      30      42      56      72      90
由于前面两次调用next()已经获取了生成器的前两个值,所以循环第一次输出的值为6

程序也可以使用list()或者tuple()将生成器能生成的值转换成列表或者元组

 17     t1 = list(test(10,1))
18 print(t1)
19 t2 = tuple(test(10,1))
20 print(t2)

程序运行结果

函数开始执行
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
函数开始执行
(0, 1, 3, 6, 10, 15, 21, 28, 36, 45)
python主要提供两种方法来创建生成器

  1. 使用for循环的生成器推导式
  2. 调用带yield语句的生成器函数

生成器是python的一个特色功能,在其他语言中往往没有对应的机制,生成器具有以下优势

  1. 当使用生成器来生成多个数据时,程序是按需获取数据的,它不会一开始酒吧所有数据都生成出来,而是next()获取下一个数据时,生成器才会执行一次,因此可以减少代码的执行次数。
  2. 当函数需要返回多个数据时,如果不使用生成器,程序就会使用列表或元组来收集函数返回的多个值,当函数要返回的数据亮比较大时,这些列表和元组会带来一定的内存开销。
  3. 使用生成器会使代码跟家简洁。

生成器的方法

当生成器运行起来后,开发者还可以为生成器提供值,通过这种方法让生成器与外部程序进行动态的数据交换

  1. 外部程序通过send()方法发送数据
  2. 生成器函数使用yield语句接收数据

只有等到程序被冻结之后,外部程序才能使用send()方法向生成器发送数据。获取生成器第一次生成的值,应该使用next()函数。如果程序非要用send()来获取生成器第一次生成的值,则不能向生成器发送数据,只能传入None参数。

  7 def square(val):
8 i = 0
9 out_val = None
10 while True:
11 #使用yield语句生成值,使用out_val来接受send()发送的
参数值
12 out_val = (yield out_val ** 2) if out_val is not No ne else (yield i ** 2)
13 #如果程序使用send()方法获取生成器的下一个值,out_va l会获取send()方法的参数值
14 if out_val is not None:
15 print("%d" % out_val)
16 i += 1

运行结果

0
1
9
81
9

上面程序第一次使用send()方法来获取生成器的下一个值,只能传入None参数。当程序冻结时,并没有给out_val进行赋值,根据运行结果可以看出第一次生成器的值为0。接下来调用next()函数获取生成器的下一个值,程序从冻结处(对out_val进行赋值)向下执行,out_val被赋值为None,所以程序执行yield i ** 2,生成器返回的结果为1,程序再次被冻结。

接下来程序调用send(9),程序从冻结处向下运行(给out_val进行赋值),此时out_val被赋值为9,生成器返回值为81

接下来程序调用next(),out_val被赋值为None,此时程序执行yield i ** 2,此时i的值已经递增为3,生成器返回的值为9

最新文章

  1. CentOS 7 安装出现 /dev/root does not exits 导致无法安装的问题
  2. shared_ptr 线程安全
  3. 洛谷 P1262 间谍网络 Label: Kosarajn强联通
  4. 不同版本strtotime("2016-09-04")输出不同问题
  5. Android WebRTC 音视频开发总结(五)-- webrtc开发原型
  6. cxGrid使用汇总2
  7. HEX和BIN文件的区别
  8. linux可执行文件目录的区别
  9. 编写一个void sort(int*x,int n)实现将x数组中的n个数据从大到小排序。n及数组元素在主函数中输入。将结果显示在屏幕上并输出到文件
  10. 详细的图文介绍如何利用XAMPP本地建站的环境配置教程
  11. JVM中GC浅解:垃圾回收的了解
  12. 设置spring-boot的logging
  13. vagrant使用小结
  14. Flask实战第6天:视图函数Response返回值
  15. TZOJ 2569 Wooden Fence(凸包求周长)
  16. 【整理】Java 9新特性总结
  17. centos6安装tomcat8.5
  18. Visual Studio 2017 调试 windows server 2016 Docker Container
  19. 安装mysql-5.6版本步骤与卸载
  20. hdoj1010 Temperor of the bone

热门文章

  1. VSCode VUE常用配置
  2. acm 快速傅里叶变换的理解
  3. Monorepo All In One
  4. Worktile vs Teambition
  5. ES6 Map vs ES5 Object
  6. macOS warning emoji render bug
  7. how to disabled alert function in javascript
  8. full stack & front end
  9. Google 灭霸 彩蛋
  10. vue components registration & vue error & Unknown custom element