一、生成器
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. 得到的值不⼀样. 列表推导式得到的是⼀个列表. ⽣成器表达式获取的是⼀个⽣成器.⽣成器的惰性机制: ⽣成器只有在访问的时候才取值