您好,登錄后才能下訂單哦!
什么是Python迭代器和生成器?相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
迭代器與可迭代對象
概念
迭代器:是訪問數(shù)據(jù)集合內(nèi)元素的一種方式,一般用來遍歷數(shù)據(jù),但是他不能像列表一樣使用下標(biāo)來獲取數(shù)據(jù),也就是說迭代器是不能返回的。
Iterator:迭代器對象,必須要實現(xiàn) next 魔法函數(shù)
Iterable:可迭代對象,繼承 Iterator,必須要實現(xiàn) iter 魔法函數(shù)
比如:
from collections import Iterable,Iterator a = [1,2,3] print(isinstance(a,Iterator)) print(isinstance(a,Iterable))
返回結(jié)果
False True
在 Pycharm 中使用 alt+b 進(jìn)去 list 的源碼中可以看到,在 list 類中有 iter 魔法函數(shù),也就是說只要實現(xiàn)了 iter 魔法函數(shù),那么這個對象就是可迭代對象。
上面的例子中 a 是一個列表,也是一個可迭代對象,那么如何才能讓這個 a 變成迭代器呢?使用 iter() 即可。
from collections import Iterable,Iterator a = [1,2,3] a = iter(a) print(isinstance(a,Iterator)) print(isinstance(a,Iterable)) print(next(a)) print('----') for x in a: print(x)
返回結(jié)果
True True 1 ---- 2 3
可以看到現(xiàn)在 a 是可迭代對象又是一個迭代器,說明列表 a 中有 iter 方法,該方法返回的是迭代器,這個時候使用 next 就可以獲取 a 的下一個值,但是要記住迭代器中的數(shù)值只能被獲取一次。
梳理迭代器 (Iterator) 與可迭代對象 (Iterable) 的區(qū)別:
可迭代對象:繼承迭代器對象,可以用 for 循環(huán)(說明實現(xiàn)了 iter 方法)
迭代器對象:可以用 next 獲取下一個值(說明實現(xiàn)了 next 方法),但是每個值只能獲取一次,單純的迭代器沒有實現(xiàn) iter 魔法函數(shù),所以不能使用 for 循環(huán)
只要可以用作 for 循環(huán)的都是可迭代對象
只要可以用 next() 函數(shù)的都是迭代器對象
列表,字典,字符串是可迭代對象但是不是迭代器對象,如果想變成迭代器對象可以使用 iter() 進(jìn)行轉(zhuǎn)換
Python 的 for 循環(huán)本質(zhì)上是使用 next() 進(jìn)行不斷調(diào)用,for 循環(huán)的是可迭代對象,可迭代對象中有 iter 魔法函數(shù),可迭代對象繼承迭代器對象,迭代器對象中有 next 魔法函數(shù)
一般由可迭代對象變迭代器對象
大家在學(xué)python的時候肯定會遇到很多難題,以及對于新技術(shù)的追求,這里推薦一下我們的Python學(xué)習(xí)扣qun:784758214,這里是python學(xué)習(xí)者聚集地??!同時,自己是一名高級python開發(fā)工程師,從基礎(chǔ)的python腳本到web開發(fā)、爬蟲、django、數(shù)據(jù)挖掘等,零基礎(chǔ)到項目實戰(zhàn)的資料都有整理。送給每一位python的小伙伴!每日分享一些學(xué)習(xí)的方法和需要注意的小細(xì)節(jié)
可迭代對象
可迭代對象每次使用 for 循環(huán)一個數(shù)組的時候,本質(zhì)上會從類中嘗試調(diào)用 iter 魔法函數(shù),如果類中有 iter 魔法函數(shù)的話,會優(yōu)先調(diào)用iter魔法函數(shù),當(dāng)然這里切記 iter 方法必須要返回一個可以迭代的對象,不然就會報錯。
如果沒有定義 iter 魔法函數(shù)的話,會創(chuàng)建一個默認(rèn)的迭代器,該迭代器調(diào)用 getitem 魔法函數(shù),如果你沒有定義 iter 和 getitem 兩個魔法函數(shù)的話,該類型就不是可迭代對象,就會報錯。
比如:
class s: def __init__(self,x): self.x = x def __iter__(self): return iter(self.x) # 這里必須要返回一個可以迭代的對象 # def __getitem__(self, item): # return self.x[item] # iter和getitem其中必須要實現(xiàn)一個 a = s('123') # 這里的a就是可迭代對象 # 這里不能調(diào)用next(a)方法,因為沒有定義 for x in a: print(x)
這里把注釋符去掉返回結(jié)果也是一樣的,返回結(jié)果:
迭代器對象
一開始提起,iter 搭配 Iterable 做可迭代對象,next 搭配 Iterator 做迭代器。next() 接受一個迭代器對象,作用是獲取迭代器對象的下一個值,迭代器是用來做迭代的,只會在需要的時候產(chǎn)生數(shù)據(jù)。
和可迭代對象不同,可迭代對象一開始是把所有的列表放在一個變量中,然后用 getitem 方法不斷的返回數(shù)值,getitem 中的 item 就是索引值。
但是 next 方法并沒有索引值,所以需要自己維護(hù)一個索引值,方便獲取下一個變量的位置。
class s: def __init__(self,x): self.x = x # 獲取傳入的對象 self.index = 0 # 維護(hù)索引值 def __next__(self): try: result = self.x[self.index] # 獲取傳入對象的值 except IndexError: # 如果索引值錯誤 raise StopIteration # 拋出停止迭代 self.index += 1 # 索引值+1,用來獲取傳入對象的下一個值 return result # 返回傳入對象的值 a = s([1,2,3]) print(next(a)) print('----------') for x in a: # 類中并沒有iter或者getitem魔法函數(shù),不能用for循環(huán),會報錯 print(x)
返回結(jié)果
Traceback (most recent call last): 1 ---------- File "C:/CODE/Python進(jìn)階知識/迭代協(xié)議/迭代器.py", line 34, in <module> for x in a: TypeError: 's' object is not iterable
上面一個就是完整的迭代器對象,他是根據(jù)自身的索引值來獲取傳入對象的下一個值,并不是像可迭代對象直接把傳入對象讀取到內(nèi)存中,所以對于一些很大的文件讀取的時候,可以一行一行的讀取內(nèi)容,而不是把文件的所有內(nèi)容讀取到內(nèi)存中。
生成器
生成器:函數(shù)中只要有 yield,這個函數(shù)就會變成生成器。每次運(yùn)行到 yield 的時候,函數(shù)會暫停,并且保存當(dāng)前的運(yùn)行狀態(tài),返回返回當(dāng)前的數(shù)值,并在下一次執(zhí)行 next 方法的時候,又從當(dāng)前位置繼續(xù)往下走。
簡單用法
舉個例子:
def gen(): yield 1 # 返回一個對象,這個對象的值是1 def ret(): return 1 # 返回一個數(shù)字1 g = gen() r = ret() print(g,r) print(next(g))
返回結(jié)果
<generator object gen at 0x000001487FDA2D58> 1 1
看完上述內(nèi)容,你們掌握什么是Python迭代器和生成器的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。