迭代器、可迭代物件、生成器
迭代器與可迭代物件
1、定義:
可迭代物件:大部分容器如 list,truples,str,sets是可迭代物件,但是他們不是迭代器。可迭代物件實現了__iter__方法,返回一個迭代器,或者使用iter(“可迭代物件”)返回一個迭代器。
迭代器:迭代器提供了一種不依賴索引取值的方式,這樣可以遍歷沒有索引的可迭代物件,比如字典、集合、檔案等等,載入這一個元素至記憶體中隨後釋放,相比之下更節省記憶體,但是我們沒有辦法獲取迭代器的長度,而且只能往後依次取值。遍歷的方法使用next(“迭代器”)
2、程式碼示例
d={'a':1,'b':2,'c':3}
s = d.__iter__() #s是一個迭代器
p = iter(“可迭代物件”) #p是一個迭代器
#遍歷迭代器
next(p)
next(p)
3、for迴圈
在for迴圈中,Python將自動呼叫工廠函式iter()獲得迭代器,自動呼叫next()獲取元素,還完成了檢查StopIteration異常的工作。如下
a = (1, 2, 3, 4)
for key in a:
print key
首先python對關鍵字in後的物件呼叫iter函式迭代器,然後呼叫迭代器的next方法獲得元素,直到丟擲StopIteration異常。
4、自定義一個迭代器:
class Fibs:
def __init__(self): #初始化
self.a = 0
self.b = 1
def __next__(self): #獲取下一個條目
self.a, self.b = self.b, self.a + self.b
return self.a
def __iter__(self): #返回迭代器
return self
fibs = Fibs() #產生一個物件
for f in fibs: #迭代
if f > 5:
break
print(f)
>>>8
next(fibs)
>>>13
next(fibs)
>>>21
生成器
1)建立生成器
在一個一般函式中使用yield關鍵字,可以實現一個最簡單的生成器,此時這個函式變成一個生成器函式。
yield與return返回相同的值,區別在於return返回後,函式狀態終止,而yield會儲存當前函式的執行狀態,在返回後,函式又回到之前儲存的狀態繼續執行。
2)為何使用生成器
記憶體使用更加高效。比如列表是在建立的時候就分配所有的記憶體空間,而生成器僅僅是需要的時候才會產生。如果我們要讀取並使用的內容遠遠超過記憶體,但是需要對所有的流中的內容進行處理,那麼生成器是一個很好的選擇。
3)生成器函式的特點
ü 生成器函式包含一個或者多個yield
ü 當呼叫生成器函式時,函式將返回一個物件,但是不會立刻向下執行
ü 生成器中__iter__()和__next__()方法等是自動實現的,所以我們可以通過next()方法對物件進行迭代
ü 一旦函式被yield,函式會暫停,控制權返回呼叫者
ü 區域性變數和它們的狀態會被儲存,直到下一次呼叫
ü 函式終止的時候,StopIteraion會被自動丟擲
4)生成器函式構造示例
l 構造迴圈生成器
逆序yield出物件的元素
def a(my_str):
length=len(my_str)
for i in range(length-1,-1,-1):
yield my_str[i]
for char in a("hello"):
print(char)
l 生成器表示式
a=(x for x in range(10))
b=[x for x in range(10)]
# 這是錯誤的,因為生成器不能直接給出長度
# print("length a:",len(a))
# 輸出列表的長度
print("length b:",len(b))
b=iter(b)
# 二者輸出等價,不過b是在執行時開闢記憶體,而a是直接開闢記憶體
print(next(a))
print(next(b))