12_python_生成器

一、生成器

 

  python中有三种方式获取生成器
  (1)通过生成器函数
  (2)通过各种推导式来实现生成器
  (3)通过数据的转换也可以获取生成器
 
  1、只要函数中存在了yield,那么这个函数就是一个生成器函数,生成器实质就是迭代器,所以生成器可以直接执行__next__()
 1 def func():
 2  print("111")
 3  yield 222
 4 gener = func() # 这个时候函数不会执行. 而是获取到⽣成器
 5 ret = gener.__next__() # 这个时候函数才会执行. yield的作用和return一样. 也是返回数据
 6 ret = gener.__next__() # 报错StopIteration
 7 print(ret)
 8 结果:
 9 111
10 222
  yield是分段来执⾏⼀个 函数. return呢? 直接停⽌执⾏函数。种使⽤⽣成器. ⼀次就⼀个. ⽤多少⽣成多少. ⽣成器是⼀个⼀个的指向下⼀个. 不会回去, __next__()到哪, 指针就指到哪⼉. 下⼀次继续获取指针指向的值. 
 
  2、send()
  send和__next__()⼀样都可以让⽣成器执⾏到下⼀个yield. 
 1 def eat():
 2     print("我吃什么啊")
 3     a = yield "馒头"
 4     print("a=",a)
 5     b = yield "烧饼"
 6     print("b=",b)
 7     c = yield "菜盒子"
 8     print("c=",c)
 9     yield "GAME OVER"
10 gen = eat() # 获取生成器
11 ret1 = gen.__next__()
12 print(ret1)
13 ret2 = gen.send("胡辣汤") # 给上一个yield传值,也就是a
14 print(ret2)
15 ret3 = gen.send("狗粮")
16 print(ret3)
17 ret4 = gen.send("猫粮")
18 print(ret4)
19 结果:
20 我吃什么啊
21 馒头
22 a= 胡辣汤
23 烧饼
24 b= 狗粮
25 菜盒子
26 c= 猫粮
27 GAME OVER
  3、send和__next__()区别: 
      (1). send和next()都是让⽣成器向下走⼀次 
      (2). send可以给上⼀个yield的位置传递值, 不能给最后⼀个yield发送值. 在第⼀次执⾏⽣成器代码的时候不能使⽤send()
 
  4、⽣成器可以使⽤for循环来循环获取内部的元素:
 1 def func():
 2     print(111)
 3     yield 222
 4     print(333)
 5     yield 444
 6     print(555)
 7     yield 666
 8 gen = func()
 9 for i in gen:
10     print(i)
11 结果:
12 111
13 222
14 333
15 444
16 555
17 666

  执行生成器的方式:

 1 第一种
 2 def func()
 3     print('hello')
 4     yield 111
 5 gen = func()
 6 for i in gen:
 7     print(i)
 8 第二种
 9 lst = list(gen)
10 print(lst)
11 第三种
12 gen.__next__()

二、推导式

  1、列表推导
     [ 结果 for 变量 in 可迭代对象 if 条件 ]
1 # 100以内能被3整除的数的平方
2 gen = (i * i for i in range(100) if i % 3 == 0)
3 for num in gen:
4  print(num)
  2、字典推导式
    {key: value for循环 if 筛选}
1 # dic = {"张无忌":"九阳神功", "乔峰":"降龙十八掌", "楚留香":"帅"}
2 # d = {dic[k]: k for k in dic}
3 # print(d)
  3、集合推导式
     {key for if}
1 # lst = ["周杰伦","周伯通","周润发","周伯通","周笔畅","周伯通","周星驰","周伯通"]
2 # s = {el for el in lst}
3 # print(s)

 

  ⽣成器表达式和列表推导式的区别:

    1. 列表推导式比较耗内存. ⼀次性加载. ⽣成器表达式⼏乎不占⽤内存. 使⽤的时候才分 配和使⽤内存

    2. 得到的值不⼀样. 列表推导式得到的是⼀个列表. ⽣成器表达式获取的是⼀个⽣成器.⽣成器的惰性机制: ⽣成器只有在访问的时候才取值

posted @ 2018-09-18 17:41  qi.hu  阅读(142)  评论(0编辑  收藏  举报