一 生成器
1什么是生产器
在python中,一边循环一边计算的机制,称为生成器(generator)。
如果直接创建一个列表,而这个列表内元素量居多,这时不仅占用很大的储存空间,如果只需要里面的前几个元素时,那么大多数元素所占空间都浪费了。
如果可以通过算法推算出列表中的元素,可以通过循坏来计算得到需要的元素,不需要创建完整的list,节省空间。
2 创建生成器
①将列表生成式的[ ]改成()
生成器保存的是算法,每次调用next(f),就计算f下一个元素的值,直到计算到最后一个元素没有元素时,抛出StopIteration异常。
但不断用next()不方便,一般是用for循环,因为生成器也是可迭代对象
3创建生成器方法②
生成器非常强大,如果算法比较复杂无法用for循环来实现的话,还可以用函数来实现。
比如,著名的斐波拉契数列(Fibonacci):
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。
print(b)改为yield b,函数就可以变成生成器了
遇到yield函数会停止,在循环过程中不断调用yield就不会中断。
但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:
4send
def fun():
i=0
while i<5:
temp=yield i
print(temp)
i+=1
执行到yield时,fun函数暂时保存,返回i的值,temp接收下次c.send('')发送过来的值,c.next()等价c.send(None)
5 多任务
多任务实现方式,协程
6 总结
生成器是这样一个函数,它记住上一次返回时在函数体中的位置。对生成器函数的第二次(或第n次)调用跳转至该函数中间,而上次调用的所有局部变量都保持不变。
生成器不仅“记住”了它数据状态;生成器还“记住”了它在流控制构造(在命令式编程中,这种构造不只是数据值)中的位置。
生成器的特点:
1.节约内存
2.迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的
二 迭代器
迭代是访问集合元素的一种方式,迭代器是可以记住遍历的位置的对象,迭代器对象从几何的第一元素开始访问,直到所有元素被访问完结束,迭代器智能往前不会后退。
1可迭代对象
可以用于for循环的数据类型:
一类是集合数据类型:list,tuple,dict,set,str等
一类是generator,包括生成器和带yield的genera function
可以直接用于for循环的对象成为可迭代对象:Iterable
2判断是否可以迭代
用isinstance()判断一个对象是否是Iterable对象
生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了
3判断对象是否为一个迭代器
可以被next()函数不断返回下一个值得对象成为迭代器:Iterator
由此可见,生成器一定是迭代器
可以使用instance()判断一个对象是否是Iterator
4 iter()函数
生成器都是Iterator对象,但list,dict,str虽然是Iterable但不是Iterator
把list,dict,str等变成Iterator 可以使用iter()函数:
5总结
凡是可以用for循环的对象都是Iterable类型
凡是可以作用于next()函数的对象都是Iterable类型
集合数据类型如list,dict,str是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象
目的:使用集合时减少占用内存
三 闭包
1函数引用
2 什么是闭包
在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包。
3 闭包的实例
在下面的例子中,函数line与变量a,b构成闭包,在创建闭包的时候,我们通过line_conf的参数a,b说明了这两个变量的取值,这样,我们就确定了函数的最终形式(y = x + 1和y = 4x + 5)。我们只需要变换参数a,b,就可以获得不同的直线表达函数。由此,我们可以看到,闭包也具有提高代码可复用性的作用。
4闭包的特点
1.闭包似优化了变量,原来需要类对象完成的工作,闭包也可以完成
2.由于闭包引用了外部函数的局部变量,则外部函数的局部变量没有及时释放,消耗内存
网友评论