每日一问:Python生成器和迭代器,with上下文管理工具

1.生成器:python

  1.1 起源:算法

      若是列表中有一万个元素,咱们只想要访问前面几个元素,对其进行相关操做,经过for循环方式效率过低,而且后面的元素会浪费内存,还会受到内存限制,因此产生生成器来解决这个问题。数组

  1.2 啥是生成器:函数

      经过某种算法推演出咱们所须要的内容,而没必要建立全部的列表元素。这种一边循环一遍计算的机制叫作生成器(generator)。经过使用yield返回值函数,每次调用yield都会暂停,将值返回出去进行计算处理。生成器相似于返回值为数组的一个函数,这个函数能够接受参数,能够被调用,可是,不一样于通常的函数会一次性返回包括了全部数值的数组,生成器一次只能产生一个值,这样消耗的内存数量将大大减少。生成器也是一个更加复杂的迭代器。spa

  1.3 建立生成器:code

      方法一:把列表生成式的 [  ]  改成 (  )  便可。对象

          generator_item = ( i*i for  i  in  range(10))    输出:<generator object <genexpr> at 0x000002A4CBF9EBA0>blog

          若是要一个个打印出来,能够经过next()函数得到generator的下一个返回值内存

          print(next(generator_item))   ==> 1generator

          print(next(generator_item))   ==> 4

          print(next(generator_item))   ==> 9

          ......

          经过这种方式(调用next()方法) ,最后会报错 StopIteration ,因此通常不用这种方法,通常用for循环遍历生成器

      方法二:经过函数的形式建立,典型例子,斐波那契数列

def fib(max): n,a,b =0,0,1
    while n < max: yield b a,b =b,a+b n = n+1
    return 'done' g = fib(6) while True: try: x = next(g) print('generator: ',x) except StopIteration as e: print("生成器返回值:",e.value) break

 

2. 迭代器:(迭代就是循环)

  2.1 定义:迭代器包含有next方法的实现,在正确的范围内返回期待的数据以及超出范围后可以抛出StopIteration的错误中止迭代。

  2.2 咱们已经知道,能够直接做用于for循环的数据类型有如下几种:

      一类是集合数据类型,如list,tuple,dict,set,str等

      一类是generator,包括生成器和带yield的generator function

    这些能够直接做用于for 循环的对象统称为可迭代对象:Iterable

    可使用isinstance()判断一个对象是否为可Iterable对象

    生成器不但能够做用于for循环,还能够被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示没法继续返回下一个值

    使用iter()函数能够将序列转化为迭代器

  2.3 小结 

  • 凡是可做用于for循环的对象都是Iterable类型;
  • 凡是可做用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
  • 集合数据类型如listdictstr等是Iterable但不是Iterator,不过能够经过iter()函数得到一个Iterator对象

3.  with上下文管理器

  一些不得不知道的知识:

上下文管理协议:context mangement protocol。协议,包含了某些方法,你们都应该跟着去作的。在这里就是 __enter__和__exit__两个方法。

上下文管理器:支持上下文管理协议的对象,这种对象实现了__enter__和__exit__方法。

as的做用:将返回的对象赋给一个变量,以方便之后的使用。

with是一个对象

运行步骤:

  1.当进入语句块时,先执行__enter__方法,把文件打开,并返回该文件对象

  2.执行代码块内容

  3.离开代码块的时候,执行__exit__方法,关闭文件。

  在执行过程当中,不管遇到什么异常,都是要离开代码块的,这个时候就由__exit__方法接管了。能够在__exit__中定义,让异常显示出来。

相关文章
相关标签/搜索