一,生成器
生成器本质就是迭代器
在python中有三种方式来获取生成器
1.通过生成器函数
2.通过各种推到式来实现生成器
3.通过数据的转换也可以获取生成器
def func(): print(11) return 22 ret = func() print(ret) # 运行结果: 11 22
将函数中的return换成yield就是生成器
#函数 def func(): print('这是函数func') return '函数func' func() # 生成器 def func1(): print('这是函数func1') yield '函数func' func1()
yield
def func(): print(1) # return 5 yield 5 print(func().__next__()) # 这样生成一个生成器 print(func().__next__()) # 这样生成一个生成器 print(func().__next__()) # 这样生成一个生成器 print(func().__next__()) # 这样生成一个生成器
def func(): print(1) yield 2 print(3) yield 4 g=func() print(g.__next__()) print(g.__next__()) # 1 # 2 # 3 # 4 print(g.__next__()) #报错 StopIteration
# def func(): # print(1) # yield 2 # # print(3) # # yield 4 # print(func().__next__()) # print(func().__next__()) # print(func().__next__()) # 1 只是形成了一个生成器,一直在重复 # 2 # 1 # 2 # 1 # 2
python2 next() iter()
python3 next() __next__() iter() __iter__()
碰到return就结束函数
碰到yield不结束就挂起
生成器的好处,非常节省内存
send
def func(): print(1) a = yield 2 # 1.挂起 2.返回值 3.接受值 print(a) # '123' print(3) b = yield 4 print(b) #'234' g = func() print(g.__next__()) #1 2 g.send(None) print(g.send('123')) # send = next+传值 # print(g.send('234')) # send = next+传值 # 1 # 2 # 123 # 3 # 4
def func(): print(1) a = yield 2 # 1.挂起 2.返回值 3.接受值 print(a) # '123' print(3) b = yield 4 print(b) #'234' c = yield 9 g = func() print(g.__next__()) #1 2 g.send(None) print(g.send('123')) # send = next+传值 print(g.send('234')) # send = next+传值 #多了一次迭代,应该再加一个yield
第一次调用生成器的时候使用send里边的值必须是None
yield from
def func(): lst = ['卫龙','老冰棍','北冰洋','牛羊配'] yield from lst g = func() for i in g: print(i)
def func(): li = [1,2,3,4] # yield li yield from li ret = func() # 把生成器的地址给了ret print(ret.__next__()) #1 # # 执行ret这个变量的指向的生成器地址 print(ret) #<generator object func at 0x000001B3B3EA97D8> # # 在全局空间找到一个变量叫做ret的,打印它的值 值就是生成器的地址
def func(): li = [1,2,3,4] l2 = [5,6,7,8] yield from li yield from l2 ret = func() # 把生成器的地址给了ret print(ret.__next__()) print(ret.__next__()) print(ret.__next__()) print(ret.__next__()) print(ret.__next__())
def func(): li = [1,2,3,4] l2 = [5,6,7,8] # yield from li # yield from l2 for i in li: yield i for em in l2: yield em # ret = func() # 把生成器的地址给了ret print(ret.__next__()) print(ret.__next__()) print(ret.__next__()) print(ret.__next__()) print(ret.__next__())
总结
1.生成器的本质就是一个迭代器
2.生成器一定是一个迭代器,迭代器不一定是一个生成器
3.生成器是可以让程序员自己定义的一个迭代器
4.生成器的好处,节省内存空间
5.生成器的特性 一次性的,惰性机制,从上向下
6.send相当于 next+传值,第一次触生成器的时候,如果使用send(None)
值必须是None,一般我建议你们使用__next__
7. python2 iter() next()
python3 iter() next() __next__() __iter__()
8.yield from 将可迭代对象元素逐个返回
二,推导式
1.列表推导式
li = [] for i in range(10): li.append(i) print(li) #[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print([i for i in range(10)])
#[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
li = [] for i in range(10): if i%2 == 1: li.append(i) print(li) #[1, 3, 5, 7, 9]
print([i for i in range(10) if i%2 == 0]) # 过滤(筛选) #[0, 2, 4, 6, 8]
#for 循环的嵌套 li = [] for i in range(10): for em in range(3): li.append(em) print(li) #[0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2]
print([j for i in range(10) for em in range(3) for j in range(5)])
2.集合推导式
s = {i for i in range(10)} print(s) #{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
3.字典推导式
print({i:i+1 for i in range(10)}) #{0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 10}
4.没有元组推导式 其实是一个生成器推导式
g = (i for i in range(10)) print(g) #<generator object <genexpr> at 0x000001D7DD1497D8>
总结
1.外部需要容器包一下, 里边第一个位置 结果 剩下位置都是语句
2.推导式 -- 面试 实现小的需求时可以使用推导式,推导式节省代码
3.推导式不要写太长,可读性查.