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

1.生成器:

1.1 起源:

如果列表中有一萬個元素,我們只想要訪問前面幾個元素,對其進行相關操作,通過for循環方式效率太低,並且後面的元素會浪費內存,還會受到內存限制,所以產生生成器來解決這個問題。

1.2 啥是生成器:

通過某種算法推演出我們所需要的內容,而不必創建所有的列表元素。這種一邊循環一遍計算的機制叫做生成器(generator)。通過使用yield返回值函數,每次調用yield都會暫停,將值返回出去進行計算處理。生成器類似於返回值為數組的一個函數,這個函數可以接受參數,可以被調用,但是,不同於一般的函數會一次性返回包括了所有數值的數組,生成器一次只能產生一個值,這樣消耗的內存數量將大大減小。生成器也是一個更加複雜的迭代器。

1.3 創建生成器:

方法一:把列表生成式的 [ ] 改為 ( ) 即可。

generator_item = ( i*i for i in range(10)) 輸出: <generator> at 0x000002A4CBF9EBA0 >/<generator>

如果要一個個打印出來,可以通過next()函數獲得generator的下一個返回值

print(next(generator_item)) ==> 1

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 類型,它們表示一個惰性計算的序列;
  • 集合數據類型如 list 、 dict 、 str 等是 Iterable 但不是 Iterator ,不過可以通過 iter() 函數獲得一個 Iterator 對象

3. with上下文管理器

一些不得不知道的知識:

上下文管理協議:context mangement protocol。協議,包含了某些方法,大家都應該跟著去做的。在這裡就是 __enter__和__exit__兩個方法。

上下文管理器:支持上下文管理協議的對象,這種對象實現了__enter__和__exit__方法。

as的作用:將返回的對象賦給一個變量,以方便以後的使用。

with是一個對象

運行步驟:

1.當進入語句塊時,先執行__enter__方法,把文件打開,並返回該文件對象

2.執行代碼塊內容

3.離開代碼塊的時候,執行__exit__方法,關閉文件。

在執行過程中,無論遇到什麼異常,都是要離開代碼塊的,這個時候就由__exit__方法接管了。可以在__exit__中定義,讓異常顯示出來。


分享到:


相關文章: