可迭代物件
概念
一個物件(在Python里面一切都是物件)只要實作了只要實作了__iter__()方法,那么這個物件就是可迭代物件
常見的可迭代物件
- 集合或序列型別(如list、tuple、set、dict、str)或檔案物件
- 在類中定義了__iter__()方法的物件,可以被認為是 Iterable物件,但自定義的可迭代物件要能在for回圈中正確使用,就需要保證__iter__()實作必須是正確的
- 在類中實作了如果只實作__getitem__()的物件可以通過iter()函式轉化成迭代器但其本身不是可迭代物件,所以當一個物件能夠在for回圈中運行,但不一定是Iterable物件,
針對第一點可以使用print(isinstance([], Iterable)) 進行校驗,回傳True則是可迭代物件,
關于第二點我們可以通過print(hasattr([], "__iter__"))回傳True知道內部實作了__iter__方法,但是這里我們需要注意的是要想被for回圈遍歷,能夠被內置的iter()函式呼叫并轉化成Iterator物件(如下代碼所示)
from collections import Iterable
class IterObj:
def __iter__(self):
return self
print(isinstance([], Iterable))
it = IterObj()
print(iter(it))
關于 第四點可以根據如下實體理解
from collections import Iterable, Iterator, Generator
class IterObj:
def __init__(self):
self.a = [3, 5, 7, 11, 13, 17, 19]
def __getitem__(self, i):
return self.a[i]
it = IterObj()
print(isinstance(it, Iterable)) # false
print(hasattr(it, "__iter__")) # false
print(isinstance(iter(it), Iterable)) # true
for i in it:
print(i) # 將列印出3、5、7、11、13、17、19
迭代器
概念
迭代器物件要求支持迭代器協議的物件,在Python中,支持迭代器協議就是實作物件的__iter__()和next()方法,其中__iter__()方法回傳迭代器物件本身;next()方法回傳容器的下一個元素,在結尾時引發StopIteration例外,簡單來說:一個物件實作了__iter__()和__next__()方法,那么它就是一個迭代器物件,
實體
class IterObj:
def __init__(self, n):
self.a = n
self.n = len(self.a)
self.i = 0
def __iter__(self):
return iter(self.a)
def __next__(self):
while self.i < self.n:
v = self.a[self.i]
self.i += 1
return v
else:
self.i = 0
raise StopIteration()
t = IterObj([3, 5, 7, 11, 13, 17, 19])
# 可以通過for遍歷
print([ i for i in t])
# 也可以通過next(因為遍歷到沒有資料時候,拋出例外所以需要捕捉下)
while True:
try:
print(t.__next__())
except:
break
區分iterable,iterator與itertion
-
itertion: 就是迭代,一個接一個(one after another),是一個通用的概念,比如一個回圈遍歷某個陣列, -
iterable: 這個是可迭代物件,屬于python的名詞,范圍也很廣,可重復迭代,滿足如下其中之一的都是iterable:-
可以
for回圈:for i in iterable -
可以按
index索引的物件,也就是定義了__getitem__方法,比如list,str; -
定義了
__iter__方法,可以隨意回傳, -
可以呼叫
iter(obj)的物件,并且回傳一個iterator
-
-
iterator:迭代器物件,也屬于python的名詞,只能迭代一次,需要滿足如下的迭代器協議-
定義了
__iter__方法,但是必須回傳自身 -
定義了
next方法,在python3.x是__next__,用來回傳下一個值,并且當沒有資料了,拋出StopIteration -
可以保持當前的狀態
-
優缺點
迭代器優點:
- 提供了一種通用不依賴索引的迭代取值方式
- 同一時刻在記憶體中只存在一個值,更節省記憶體
迭代器缺點:
- 取值不如按照索引的方式靈活,不能取指定的某一個值,只能往后取,不能往前去
- 無法預測迭代器的長度
生成器
概念
生成器就是一種自定義的迭代器,本質為迭代器,但凡函式內包含yield關鍵字,呼叫函式不會執行函式體代碼,會得到一個回傳值,該回傳值就是生成器物件,在廖雪峰教程中解釋為:在Python中,這種一邊回圈一邊計算的機制,稱為生成器(Generator)
注意: 生成器既是可迭代的也是迭代器
定義生成器有兩種方式:
- 串列生成器
- 使用
yield定義生成器函式 (yield是一個語法糖,內部實作了迭代器協議,同時保持狀態可以掛起)
串列生成器
from collections import *
g = (x for x in range(3)) # 0~18的偶數生成器
print(isinstance(g, Iterable)) # true
print(isinstance(g, Iterator)) # true
print(isinstance(g, Generator)) # true
print(hasattr(g, "__iter__")) # true
print(hasattr(g, "__next__")) # true
print(next(g)) # 0
print(next(g)) # 1
print(next(g)) # 2
使用yield定義生成器函式
def gen():
for i in range(10):
yield i
# 檢索資料,開始執行
a = gen()
print(list(a))
# 呼叫gen()并沒有真實執行函式,而是只是回傳了一個生成器物件
# 執行第一次a.next()時,才真正執行函式,執行到yield一個回傳值,然后就會掛起,
# 保持當前的名字空間等狀態,然后等待下一次的呼叫,從yield的下一行繼續執行,
a = gen()
print(a.__next__())
這里yield的作用就相當于return,這個函式就是順序地回傳[0,9]的之間的自然數,可以通過next()或使用for回圈來遍歷,當程式遇到yield關鍵字時,這個生成器函式就回傳了,直到再次執行了next()函式,它就會從上次函式回傳的執行點繼續執行,即yield退出時保存了函式執行的位置、變量等資訊,再次執行時,就從這個yield退出的地方繼續往下執行,
迭代器和生成器的區別
生成器能做到迭代器能做的所有事,而且因為自動創建了 iter()和 next()方法,生成器顯得特別簡潔,而且生成器也是高效的,使用生成器運算式取代串列決議可以同時節省記憶體,
參考鏈接
python的迭代器為什么一定要實作__iter__方法?
Python:range 物件并不是迭代器(英文)
Python:range 物件并不是迭代器
python迭代器與生成器小結
python迭代器和for回圈區別
Python迭代器,生成器--精華中的精華
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/152675.html
標籤:其他
上一篇:python 類關聯關系
下一篇:爬蟲心得
