python中生成器表达式_Python的生成器和生成器表达式

一,生成器和生成器表达式

什么是生成器,生成器实质就是迭代器,在python中有三种方式来获取生成器:

1. 通过生成器函数

和普通函数没有区别,里面有yield的函数就是生成器函数,生成器函数在执行的时候.,默认不会执行函数体.,返回生成器通过生成器的__next__()分段执行这个函数

send() 给上一个yield传值, 不能再开头(没有上一个yield), 最后一个yield也不可以用send()

先来看一下简单的函数

1 def xue(): #创建一个函数

2 print('学')3 return 'Python' #生成器

4 xue1 =xue()5 print(xue1)6 结果:7 学8 Python

函数中的return换成yield这就是一个生成器

1 defxue():2 print('学')3 yield 'Python'

4 xue1 =xue()5 print(xue1)6 结果:7

运行结果跟上面的不一样,因为由于函数中存在yield,那么这个函数就是一个生成器函数,这个时候我们在执行这个函数的时候,就不再是函数的执行了,而是获取这个生成器,如何使用呢?想想迭代器,生成器的本质就是迭代器,所以,我们可以直接执行__next__()来执行以下生成器

1 defxue():2 print('学')3 yield 'Python'

4 xue1 = xue() #这时候函数不会执行,而是获取到生成器

5 YJ = xue1.__next__()#这个时候函数才会执⾏行yield的作⽤用和return一样. 也是返回数据

6 print(YJ)7 结果:8 学9 Python

yield和return的区别就是,yield是分段来执行一个函数,return是直接停止执行函数

1 defxue():2 print('学')3 yield 'Python'

4 print('也学')5 yield 'java'

6 xue1 = xue() #这时候函数不会执行,而是获取到生成器

7 YJ = xue1.__next__()8 print(YJ)9 YJ1 = xue1.__next__()10 print(YJ1)11 YJ2 = xue1.__next__() #最后一个yield执行完毕,再次__next__()程序报错,也就是说和return无关了

12 print(YJ2)

结果:

当程序运行完最后一个yield,那么后面继续进行__next__()

需求:某学校要订购50000套校服,工厂直接生产50000套校服,但是学校也没有5000个学生,也没有教室放置一次性生产那么多,最后的效果会是什么呢?直接生产50000件校服,刷一下量大的话把你内存撑满!!!

1 defxiaofu():2 lst =[]3 for el in range(0,50000):4 lst.append('校服'+str(el))5 returnlst6 xiaofu()7 print(xiaofu())

我要一套你给一套,一共50000,是不是很完美

defxiaofu():for el in range(0,50000):yield '校服'+str(i)

xf=xiaofu()print(xf.__next__())print(xf.__next__())print(xf.__next__())print(xf.__next__())

两者的区别,第一种是直接一次性全部拿出来,会很占用内存,第二种是使用生成器,一次就一个,用多少生产多少,直到生产完,生成器是一个一个的指向下一个,不会回去,__next__()到哪,指针就指到哪儿,下一次继续获取指针指向的值

send方法,send和__next__()一样都可以让生成器执行到下一个yield

1 defxue():2 print('要学')3 a = yield 'Python'

4 print('a=',a)5 b = yield 'java'

6 print('b=', b)7 c = yield 'PHP'

8 print('c=', c)9 yield 'YJ加油!'

10 xue1 = xue() #获取生成器

11 fh = xue1.__next__()12 print(fh)13 #结果:要学

14 #Python

15 fh1 = xue1.send('VB')16 print(fh1)17 #结果:a= VB

18 #java

19 fh2 = xue1.send('C#')20 print(fh2)21 #结果:b= C#

22 #PHP

23 fh3 = xue1.send('C++')24 print(fh3)25 #结果:c= C++

26 #YJ加油!

send和__next__()的区别

1.send和next()都是让生成器向下走一次

2.send可以给上一个yield的位置传递值,不能给最后一个yield发送值,在第一次执行生成器代码的时候不能使用send()

生成器可以使用for需变换来循环获取内部元素:

1 defxue():2 print('要学')3 a = yield 'Python'

4 print('a=',a)5 b = yield 'java'

6 print('b=', b)7 c = yield 'PHP'

8 print('c=', c)9 yield 'YJ加油!'

10 xue1 =xue()11 for el inxue1:12 print(el)

结果:

2. 通过各种推导式来实现生成器

1. 列表推导式 [结果 for循环 条件筛选]

2. 字典推导式 {k:v for循环 条件筛选}

3. 集合推导式 {k for循环 条件}

3. 通过数据的转换也可以获取生成器

二.,生成器表达式,列表推导式,以及其他推导式

我们来看一段代码,给出一个空列表,通过for循环向列表添加1-15个数字:

1 lst =[]2 for i in ramge(1,16):3 lst.append(i)4 print(lst)5 结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,15]

列表推导式写法:

1 #推导式2 lst = [i for i in range(1,16)]3 print(lst)4 结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]

两者的结果是不是一样?列表推导式比较简洁,列表推导式是通过一行来构建你要的列表,列表推导式看起来代码简单,但是出现错误之后就很难排查

列表推导式的写法:[结果  for  变量  in  可迭代对象]

需求:从1-19岁写入到lst列表中

1 lst = [str(i)+'岁' for i in range(1,20)]2 print(lst)3 结果:['1岁', '2岁', '3岁', '4岁', '5岁', '6岁', '7岁', '8岁', '9岁', '10岁', '11岁', '12岁', '13岁', '14岁', '15岁', '16岁', '17岁', '18岁', '19岁']

我们还可以对列表中的数据进行筛选,筛选写法:

[ 结果  for  变量  in  可迭代对象  if  条件 ]

#获取1-100内所有的偶数

1 lst = [i for i in range(1,100) if i % 2 ==0]

2 print(lst)

生成器表达式和列表推导式的语法基本是一样的,只是把[]换成()

1 YJ = (i for i in range(1,15))2 print(YJ)3 结果为:4 at 0x000002CE3ABA5660>

上面的结果就是一个生成器,我们可以使用for循环来获取这个生成器

1 YJ = ('我今年%s岁了' % i for i in range(20))2 for i inYJ:3 print(i)4 结果:5 我今年0岁了6 我今年1岁了7 我今年2岁了8 我今年3岁了9 我今年4岁了10 我今年5岁了11 我今年6岁了12 我今年7岁了13 我今年8岁了14 我今年9岁了15 我今年10岁了16 我今年11岁了17 我今年12岁了18 我今年13岁了19 我今年14岁了20 我今年15岁了21 我今年16岁了22 我今年17岁了23 我今年18岁了24 我今年19岁了

生成器表达式也是可以进行筛选的

获取1-100内能被3整除的数

1 #获取1-100内能被3整除的数

2 YJ = (i for i in range(1,100) if i % 3 ==0)3 print(YJ)4 #结果: at 0x000002164AC95660>

5 for i in YJ: #使用for循环来循环这个生成器拿结果

6 print(i)7 结果;8 3,6,9,12,15...99

100以内能被3整除的数的平方

1 YJ = (i * i for i in range(100) if i % 3 ==0)2 for i in YJ: #使用for循环来循环这个生成器拿结果

3 print(i)

生成器表达式跟列表推导式的区别:

1.列表推导式比较耗内存,一次性加载,生成器表达式几乎不占内存,使用的时候才分配和使用内存

2.得到的值不一样,列表推导式得到的是一个列表,生成器表达式获取的是一个生成器

生成器有惰性机制,生成器只有访问的时候才取值,说白了,你找它要它才会给你值,不找不给它也不会执行

字典推导式:

根据名字也能猜到,推到出来的是字典

1 dic = {'a' : 1, 'b' : 2, 'c' : 3}2 dic1 = {dic[key] : key for key indic}3 print(dic1)4 #结果:{1: 'a', 2: 'b', 3: 'c'}

集合推导式:

集合推导式可以帮我们直接生成一个集合,集合的特点是无序,不重复,所有集合推导式自带去重功能

1 lst = [1,1,2,3,3,66,66,8,9]2 a = {abs(i) for i inlst}3 print(a)4 #结果:{1, 2, 3, 66, 8, 9}

总结:推导式有,列表推导式,字典推导式,集合推导式,切记切记!!!元组是没有推导式的

生成器表达式:(结果 for 变量量 in 可迭代对象 if 条件筛选)

生成器表达式可以直接获取到生成器对象,生成器对象可以直接进行for循环,生成器具有惰性机制!!!

2019年11月13日

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值