一、生成器
生成器的本质就是迭代器。
def func(): print(1) yield 5 print(2) yield 9 g = func() print(g.__next__()) print(g.__next__())
这里的func()就是一个生成器,yield就是生成器的标志。把函数里的return换成yield这个函数就变成了生成器。区别于return,当程序执行到yield时并不会结束,而是会挂起函数,下一次使用生成器会从挂起处继续执行直到下一个yield……就像玩游戏时的存档和读档,每次登陆后不需要从头再玩一遍,直接从上一次的结束位置开始。
yield的作用除挂起函数还有返回值和接收值的作用。
第一次调用生成器的时候使用send里边的值必须是None
def func(): li = [1,2,3,4] # yield li yield from li ret = func() # 把生成器的地址给了ret print('is ret',ret.__next__()) # 执行ret这个变量的指向的生成器地址 print('is ret',ret) # 在全局空间找到一个变量叫做ret的,打印它的值 值就是生成器的地址
总结:
1.生成器的本质就是一个迭代器
2.生成器一定是一个迭代器,迭代器不一定是一个生成器
3.生成器是可以让程序员自己定义的一个迭代器
4.生成器的好处,节省内存空间
5.生成器的特性 一次性的,惰性机制,从上向下
6.send相当于 next+传值,第一次触生成器的时候,如果使用send(None)
值必须是None,一般我建议你们使用__next__
7. python2 iter() next()
python3 iter() next() __next__() __iter__()
8.yield from 将可迭代对象元素逐个返回
二、推导式
列表推导式
li = [] for i in range(10): li.append(i) print(li)
上面列表的生成可以用列表推导式写成:
print([i for i in range(10)])
列表推导式的结构为:
[ 结果 语法 ]
同样的还有集合推导式和字典推导式:
s = {i for i in range(10)}
print(s)
print({i:i+1 for i in range(10)})
要注意的是没有元组推导式,如下,是生成器推导式
g = (i for i in range(10))
推导式可以大大的节俭代码,但当表达式过多的时候不推荐用。
1.外部需要容器包一下,里边第一个位置 结果 剩下位置都是语句
2.推导式-- 面试 实现小的需求时可以使用推导式,推导式节省代码
3.推导式不要写太长,可读性查,排错困难