今日主要内容
1. 生成器和生成器函数
生成器的本质就是迭代器
生成器的三种创建办法:
1.通过生成器函数
2.通过生成器表达式创建生成器
3.通过数据转换
2. 生成器函数:
函数中包含了yield的就是生成器函数
注意:生成器函数被执行. 获取到的是生成器. 而不是函数的执行
3. 与return比较
函数中存在yield,
优点:用多少生成多少
节约内存
yield 返回结果,让函数分段执行
return 直接返回函数结果,结束函数的调用
def func():
yield 11
yield 22
yield 33
yield 44
g = func() # 拿到的是生成器. 生成器的本质是迭代器. 迭代器可以被迭代 生成器可以直接for循环
for i in g:
print(i) # 本质上执行的是__next__()
it = g.__iter__()
while True:
try:
print(it.__next__())
except StopIteration:
break
4. send和__next__()区别:
1. send和next()都是让⽣生成器向下走一次
2. send可以给上⼀一个yield的位置传递值, 不能给后⼀一个yield发送值. 在第⼀次执⾏生
成器代码的时候不能使⽤用send(),最后一次结束的时候也不能使用
5. 生成器表达式:
(结果 for 变量 in 可迭代对象 if 筛选)
6. 取值:
1. __next__()
2. send(值) 给上一个yield位置传一个值, 第一个和最后一个yield不用传值
3. 可以for循环 (获取内部的元素:)
4. list(g)
2. 各种推倒式和生成器表达式
1. 列表推倒式 [结果 for 变量 in 可迭代对象 if 筛选]
lst = [i for i in range(1, 15)]
print(lst)
2. 字典推倒式 {结果 for 变量 in 可迭代对象 if 筛选} 结果=>key:value
3. 集合推倒式 {结果 for 变量 in 可迭代对象 if 筛选} 结果=>key
3.⽣生成器表达式和列列表推导式的区别:
1. 列表推导式比较耗内存. ⼀一次性加载. 生成器表达式几乎不占⽤用内存. 使用的时候才分 配和使用内存
2. 得到的值不⼀一样. 列表推导式得到的是⼀一个列表. 生成器表达式获取的是⼀一个生成器.
生成器的惰性机制:⽣生成器只有在访问的时候才取值. 说⽩白了了. 你找他要他才给你值. 不找他 要. 他是不会执⾏行行的.
def func():
print(111)
yield 222
g = func() # ⽣生成器器g
g1 = (i for i in g) # ⽣生成器器g1. 但是g1的数据来源于g
g2 = (i for i in g1) # ⽣生成器器g2. 来源g1 print(list(g)) # 获取g中的数据. 这时func()才会被执⾏行行. 打印111.获取到222. g完毕.
print(list(g1)) # 获取g1中的数据. g1的数据来源是g. 但是g已经取完了了. g1 也就没有数据 了了
print(list(g2)) # 和g1同理理 例2 惰性机制的应用
def add(a, b):
return a + b
def gen():
for r_i in range(4):
yield r_i
g = gen()
for n in [2, 10]:
g = (add(n, i) for i in g)
#g = (add(n,i) for i in (add(n, i) for i in g)) #g 由于惰性机制,for循环第一次并未取值
# g = (add(10,i) for i in (add(10, i) for i in (0,1,2,3)))
print(list(g))