迭代器與生成器
我們知道,可以使用for循環(huán)操作的數(shù)據(jù)類型有l(wèi)ist、str、dict、set、tuple,以及生成器,它們都是可迭代對(duì)象,可以被next()函數(shù)調(diào)用并不斷返回下一個(gè)值的對(duì)象稱為迭代器(Iterator)。
迭代器包含有next方法的實(shí)現(xiàn),在正確的范圍內(nèi)返回期待的數(shù)據(jù)以及超出范圍后能夠拋出StopIteration的錯(cuò)誤停止迭代。
list、dict、str雖然是可迭代對(duì)象,但并不是迭代器,python中的迭代器是一個(gè)數(shù)據(jù)流,或者有序序列,但是我們無(wú)法提前知道序列的長(zhǎng)度,只能通過next函數(shù)不斷計(jì)算下一個(gè)數(shù)據(jù)。我們可以通過iter函數(shù)將它們轉(zhuǎn)變?yōu)榈?,其?shí)python中的for本質(zhì)上是通過不斷調(diào)用next函數(shù)實(shí)現(xiàn)的。
列表是python中非常重要的數(shù)據(jù)結(jié)構(gòu),但是,如果我們要?jiǎng)?chuàng)建一個(gè)很大的列表,其中包含很多個(gè)元素(例如10億個(gè)),如果把每個(gè)元素放在列表中就會(huì)超出內(nèi)存的限制,而且我們有時(shí)只訪問前面幾個(gè)元素,后面的內(nèi)存就會(huì)浪費(fèi)掉。如果我們根據(jù)前一個(gè)元素就可以獲得下一個(gè)元素,即知道元素的獲取規(guī)則,就不必創(chuàng)建完成的列表,在python中這種一邊循環(huán)一邊生成列表元素的機(jī)制稱為生成器。
生成器函數(shù)是用def定義的,利用關(guān)鍵字yield一次性返回一個(gè)結(jié)果,阻塞后重新開始。生成器是一種特殊的迭代器。
下面,我們實(shí)現(xiàn)一個(gè)我們自己的range方法,以下函數(shù)實(shí)際上就是一個(gè)生成器,實(shí)現(xiàn)從0到n-1的數(shù)字生成,yield關(guān)鍵字可以理解為return,但是不同的是,執(zhí)行完代碼后,又會(huì)返回到函數(shù)yield處繼續(xù)執(zhí)行。
def my_range(n):
i = 0
while i < n:
yield i
i = i + 1
我們打印出來該函數(shù)的結(jié)果,可以發(fā)現(xiàn)是一個(gè)生成器:
print(my_range(5))
# <generator object my_range at 0x0000023D3C9270A0>
如何使用生成器?最簡(jiǎn)單的方式就是使用for循環(huán),逐一取出生成器生成的元素,生成器每次只生成一個(gè)元素:
for i in my_range(5):
print(i)
# 0
# 1
# 2
# 3
# 4
此外,還可以使用next方法,每次只取一個(gè)元素:
a = my_range(5)
print(next(a))
# 0
print(next(a))
# 1
print(next(a))
# 2
有關(guān)迭代器和生成器的更多內(nèi)容可以參考大佬博客。