python中的生成器

一.生成器(generator)

生成器的实质就是迭代器
生成器表达式:

1 def func():
2     print('111')
3     yield 222
三种执行生成器的方式
1.通过g.__next__(),send()来实现生成器
1 def func():
2     print(111)
3     yield 222
4     # yield 112
5 g=func()
6 print(g.__next__())
2.通过各种推导式来实现生成器(for)
1 def func():
2     print(111)
3     yield 222
4     # yield 112
5 g=func()
6 g1=[i for i in func()]
7 print(g1)
3.通过数据的转换也可以实现生成器:list(),tuple()
1 def func():
2     print(111)
3     yield 222
4     # yield 112
5 g=func()
6 # g1=[i for i in func()]
7 print(list(g))   #获得列表
yield和return的区别:
yield是分段执行一个函数,return是直接停止执行函数
 1 def func():
 2     print('111')
 3     yield 222
 4     print('333')
 5     yield 444
 6 gener=func()
 7 ret=gener.__next__()#222
 8 print(ret)
 9 ret2=gener.__next__()#444
10 print(ret2)
11 ret3=gener.__next__()#    ret3=gener.__next__()   __next__()如果多了会报错
12 StopIteration
13 print(ret3)
生成器省内存的原因:
1 def cloth():
2     lis=[]
3     for i in range(10000):
4         lis.append(i)
5     print(lis)
6 cloth()#c此时lis列表将所有的值全部都拿出来了,所以非常耗内存
1 def cloth():
2     for i in range(10000):
3         yield i
4 gener=cloth()
5 print(gener.__next__())
6 print(gener.__next__())
7 print(gener.__next__())#一次就一个 用多少生成多少
send()方法:

 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 gener=eat()
11 ret=gener.__next__()
12 print(ret)
13 ret2=gener.send('胡辣汤')
14 print(ret2)
15 ret3=gener.send('猫粮')
16 print(ret3)
17 ret4=gener.send('大鱼大肉')
18 print(ret4)
send() 给上一个yield传值, 不能再开头(没有上一个yield), 最后一个yield也不可以用send()

send()和__next__()的区别:
send和next都是让生成器向下走一次,但是send可以给上一个yield的位置传值

二.推导式

2.1列表推导式
1 lst=[i for i in range(10) if i%2==0]
2 print(lst)
写法:[结果 for循环 条件]
1 lis=['我是天下第%s美' % i for i in range(1,5) if i%2==1]
2 print(lis)
2.2.字典推导式
1 dic={'第一美':'','第一帅':'靳文博'}
2 dic_new={value:key for key,value in dic.items()}
3 print(dic_new)
写法同列表推导式

2.3集合推导式
1 lst=[1,1,2,2,3,4,5]
2 set={i for i in lst}
3 print(set)  #自带去重复的功能
写法同列表推导式

2.4 生成器表达式
生成器表达式的语法与以上三个推导式的语法基本上是一样的,只是把[]换成()
1 gener=(i for i in range(5))
2 print(gener)  #<generator object <genexpr> at 0x000001D161B6CF68>  结果告诉我们这是一个生成器
获取10以内能被3整除的数
1 gener=(i for i in range(10) if i%3==0)
2 for i in gener:
3     print(i)
生成器表达式和列表推导式的区别:
1.列表推导式比较耗内存,一次全加载出来,生成器表达式几乎不耗内存,使用一个出来一个

生成器的惰性机制
1 def func():
2     print('111')
3     yield 222
4 g=func()   #获取生成器
5 g1=(i for i in g)   #也是生成器
6 g2=(i for i in g1)   #也是生成器
7 print(tuple(g))
8 print(list(g1))   #执行的时候源头已经没有数据了,生成器无法后退
9 print(list(g2))
例子
 1 def add(a,b):
 2     return  a+b
 3 
 4 def test():
 5     for i in range(4):
 6         yield i
 7 g=test()
 8 
 9 for n in [2,10]:
10     g=(add(n,i)  for i in g)    #此时的n不会带值
11 
12 print(list(g))#归根结底还是惰性机制,这里只有 list()才会拿值
13 [20, 21, 22, 23]

小知识点1:

如何把一行代码换成两行:

在你想换行的地方后面加,然后接着写就行了

 

原文地址:https://www.cnblogs.com/shanghongyun/p/9469840.html