12_python_生成器

时间:2023-03-09 05:43:50
12_python_生成器

一、生成器

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

  执行生成器的方式:

 第一种
def func()
print('hello')
yield 111
gen = func()
for i in gen:
print(i)
第二种
lst = list(gen)
print(lst)
第三种
gen.__next__()

二、推导式

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

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

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

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