一、生成器

生成器的本质就是迭代器。

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.推导式不要写太长,可读性查,排错困难