一、生成器
我们知道的迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处就是节省内存。
如果某些情况下,我们需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。总而言之生成器就是我们自己写的迭代器。
Python中提供的生成器:
1.生成器函数:常见函数定义,但是使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数状态,以便下次从离开的地方继续执行。个人理解就是有一个记忆功能,会记住这次执行结束的状态,然后下次执行的时候从这里继续,每次都是以此往复。
2.生成器表达式:类似于列表推导,但是生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表。
生成器Generator
本质:迭代器(所以自带了__iter__和__next__方法)
特点:惰性运算、开发者自定义
二、生成器函数
一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会返回具体的值,而是得到一个可迭代对象。每一次获得这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数结束。
import time def genrator_fun1(): a = 1 print('现在定义了a变量') yield a b = 2 print('现在又定义了b变量') yield b g1 = genrator_fun1() print('g1 : ',g1) #打印g1可以发现g1就是一个生成器 print('-'*20) #我是华丽的分割线 print(next(g1)) time.sleep(1) #sleep一秒看清执行过程 print(next(g1))
生成器有什么作用么?
省内存
三、send
def generator(): print(123) content = yield 1 print('=======',content) print(456) yield2 g = generator() ret = g.__next__() print('***',ret) ret = g.send('hello') #send的效果和next一样 print('***',ret) #send 获取下一个值的效果和next基本一致 #只是在获取下一个值的时候,给上一yield的位置传递一个数据 #使用send的注意事项 # 第一次使用生成器的时候 是用next获取下一个值 # 最后一个yield不能接受外部的值
四、Python的三大推导式
1.列表推导式和生成器表达式
l = [i for i in range(10)] print(l) l1 = ['选项%s'%i for i in range(10)] print(l1)
1.把列表推导式的[]换成()就得到了生成器表达式(generator)
2.列表推导式与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存
3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如,sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以我们可以直接这样计算一系列值的和:
sum(x ** 2 for x in range(4))
2.字典推导式
字典推导和列表推导的使用方法十分类似,只不过把[]改成了{}。上代码:
dic_old = {'a':10, 'b':20} dic_new = {value:key for key,value in dic_old.items()} # 变key和value的位置 print(dic_new) #执行结果 #{10: 'a', 20: 'b'}
3.集合推导式
集合推导式有十分类似,唯一的区别就是集合使用{},上代码:
set_test= {x**2 for x in [1, 1, 2, 2, 3, 4]} print(set_test) # 执行结果 # {16, 1, 4, 9} #好像有问题哦,怎么6个元素求幂之后丢了两个,往下看↓
#请不要忘记集合是无序的并且会自动去重哦