每日一問: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__中定義,讓異常顯示出來。

相關文章
相關標籤/搜索