生成器
生成器的特点
一、内存空间的角度
1、普通列表会将所有元素存到内存中,因此可以进行切片式操作。如果列表元素很多,加载到内存中的时间就会很长。
2、生成器只能for循环的过程中提取,根据垃圾清理机制,无论生成器内有多少元素,都只会占用一个内存地址。
二、调用方式:
1、普通列表的调用方法有很多,比如切片,添加,删除等等。
2、生成器只有在调用时才会生成相应的数据,调用方式有 " str__next__.() str.send() ",并且每调用一次就产生一个值调用到最后一个值后会报错(可用:异常处理)。
注意:
next:是直接调用yield,并不会传值。
send:是调用并直接传值给yield。
三、列表生成器和生成器格式:
1、列表生成器:
[ i * 2 for i in range(10) ]
结果显示:[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
2、生成器:
( i * 2 for i in range(10) )
结果显示:<generator object <genexpr> at 0x00000000006E87D8>
注意:如果有1亿行记录
第一个格式的效果可能花费5分钟或者跟多时间。
第二个格式基本上是毫秒级的,因为只获取一个内存地址
列表生成器
一、列表生成器的种类:
1、普通列表:
a = [1,2,3]
2、列表生成器:(每次循环都*2)
[i*2 for i in range(10)]
1 相当于: 2 a = [] 3 for i in rang(10): 4 a.append(i*2) 5 6 print(a)
注意:类似python 2.7里的range(100)和xrange(100)
1、rang:是逐个返回1~100范围值。
2、xrang:是返回一个内存地址,该地址包含了100的值,只有在for循环时才会显示
3、使用xrang的优势,结合python的垃圾回收机制,可以循环使用同一个
二、两个列表的区别:
a:是写死的。
列表生成器:是可扩展的。
生成器概念
1、具有生成能力的函数叫生成器。
2、具有取东西能力的函数叫迭代器。
3、主要关注生成器如何去写;迭代器主要是python内部封装好的;无需过多关注
一、通过filter进行结果过滤:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 li = [11,22,33,44,55,34] 2 result= filter(lambda x:x>33,li) 3 print(result) 4 5 返回一个对象: 6 <filter object at 0x0000000000A55128> 7 8 9 #返回结果:具有生成指定条件数据的能力的一个对象。只有在循环它的时候生成 10 #是一个内存地址,该地址包括大于33的所有值 11 #该结果只有在for循环时才会显示
二、使用yield()转成生成器。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def func(): 2 yield 1 3 yield 1 4 yield 1 5 6 ret = func() 7 print('ret:',ret) 8 9 显示结果 10 ret: <generator object func at 0x0000000000A38938> 11 12 13 #只要函数中出现yield,则会变成生成器,返回内存地址<generator object func at 0x00000000011388E0>
当用for循环遍币ret时,内存地址则会转换成数值,如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 for i in ret: 2 print('foi循环:',i) 3 4 5 6 显示结果: 7 foi循环: 1 8 foi循环: 1 9 foi循环: 1
注释:
当for循环进入函数时,会找到yield1,并打印1,然后返回结果。
当在一次for循环时,会找到上一次的执行结果1,然后从上次执行结果后在执行一个2,并且返回。
多次for循环,以此类推。
三、生成器的属性:
生成器是由于函数创建的,而函数名就是生成器。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 def myrange(arg): 2 start = 0 3 while True: 4 if start > arg: 5 return 6 yield start 7 start += 1 8 9 ret = myrange(3) 10 11 r = ret.__next__() #进入函数,找到yield,获取yield后面的数据,每运行一次,生成器就会往下执行一个数值: 12 print(r) 13 r = ret.__next__() 14 print(r) 15 r = ret.__next__() 16 print(r) 17 r = ret.__next__() 18 print(r) 19 20 显示结果: 21 0 22 1 23 2 24 3