當前位置:成語大全網 - 新華字典 - python 叠代器和生成器的區別

python 叠代器和生成器的區別

Num01–>叠代器

定義:

對於list、string、tuple、dict等這些容器對象,使用for循環遍歷是很方便的。在後臺for語句對容器對象調用iter()函數。iter()是python內置函數。

iter()函數會返回壹個定義了next()方法的叠代器對象,它在容器中逐個訪問容器內的元素。next()也是python內置函數。在沒有後續元素時,next()會拋出壹個StopIteration異常,通知for語句循環結束。

叠代器是用來幫助我們記錄每次叠代訪問到的位置,當我們對叠代器使用next()函數的時候,叠代器會向我們返回它所記錄位置的下壹個位置的數據。實際上,在使用next()函數的時候,調用的就是叠代器對象的_next_方法(Python3中是對象的_next_方法,Python2中是對象的next()方法)。所以,我們要想構造壹個叠代器,就要實現它的_next_方法。但這還不夠,python要求叠代器本身也是可叠代的,所以我們還要為叠代器實現_iter_方法,而_iter_方法要返回壹個叠代器,叠代器自身正是壹個叠代器,所以叠代器的_iter_方法返回自身self即可。

壹些術語的解釋:

1,叠代器協議:對象需要提供next()方法,它要麽返回叠代中的下壹項,要麽就引起壹個StopIteration異常,以終止叠代。

2,可叠代對象:實現了叠代器協議對象。list、tuple、dict都是Iterable(可叠代對象),但不是Iterator(叠代器對象)。但可以使用內建函數iter(),把這些都變成Iterable(可叠代器對象)。

3,for item in Iterable 循環的本質就是先通過iter()函數獲取可叠代對象Iterable的叠代器,然後對獲取到的叠代器不斷調用next()方法來獲取下壹個值並將其賦值給item,當遇到StopIteration的異常後循環結束

Python自帶容器對象案例:

# 隨便定義壹個listlistArray=[1,2,3]# 使用iter()函數iterName=iter(listArray)

print(iterName)# 結果如下:是壹個列表list的叠代器# <list_iterator object at 0x0000017B0D984278>print(next(iterName))

print(next(iterName))

print(next(iterName))

print(next(iterName))#沒有叠代到下壹個元素,直接拋出異常# 1# 2# 3# Traceback (most recent call last):# File "Test07.py", line 32, in <module># StopIteration123456789101112131415161718

Python中壹個實現了_iter_方法和_next_方法的類對象,就是叠代器,如下案例是計算菲波那切數列的案例

class Fib(object):

def __init__(self, max):

super(Fib, self).__init__()

self.max = max def __iter__(self):

self.a = 0

self.b = 1

return self def __next__(self):

fib = self.a if fib > self.max: raise StopIteration

self.a, self.b = self.b, self.a + self.b return fib# 定義壹個main函數,循環遍歷每壹個菲波那切數def main():

# 20以內的數

fib = Fib(20) for i in fib:

print(i)# 測試if __name__ == '__main__':

main()12345678910111213141516171819202122232425262728

解釋說明:

在本類的實現中,定義了壹個_iter_(self)方法,這個方法是在for循環遍歷時被iter()調用,返回壹個叠代器。因為在遍歷的時候,是直接調用的python內置函數iter(),由iter()通過調用_iter_(self)獲得對象的叠代器。有了叠代器,就可以逐個遍歷元素了。而逐個遍歷的時候,也是使用內置的next()函數通過調用對象的_next_(self)方法對叠代器對象進行遍歷。所以要實現_iter_(self)和_next_(self)這兩個方法。

而且因為實現了_next_(self)方法,所以在實現_iter_(self)的時候,直接返回self就可以。

總結壹句話就是:

在循環遍歷自定義容器對象時,會使用python內置函數iter()調用遍歷對象的_iter_(self)獲得壹個叠代器,之後再循環對這個叠代器使用next()調用叠代器對象的_next_(self)。

註意點:_iter_(self)只會被調用壹次,而_next_(self)會被調用 n 次,直到出現StopIteration異常。

Num02–>生成器

作用:

>延遲操作。也就是在需要的時候才產生結果,不是立即產生結果。12

註意事項:

>生成器是只能遍歷壹次的。

>生成器是壹類特殊的叠代器。123

分類:

第壹類:生成器函數:還是使用 def 定義函數,但是,使用yield而不是return語句返回結果。yield語句壹次返回壹個結果,在每個結果中間,掛起函數的狀態,以便下次從它離開的地方繼續執行。

如下案例加以說明:

# 菲波那切數列def Fib(max):

n, a, b = 0, 0, 1

while n < max: yield b

a, b = b, a + b

n = n + 1

return '親!沒有數據了...'# 調用方法,生成出10個數來f=Fib(10)# 使用壹個循環捕獲最後return 返回的值,保存在異常StopIteration的value中while True: try:

x=next(f)

print("f:",x) except StopIteration as e:

print("生成器最後的返回值是:",e.value) break123456789101112131415161718

第二類:生成器表達式:類似於列表

,只不過是把壹對大括號[]變換為壹對小括號()。但是,生成器表達式是按需產生壹個生成器結果對象,要想拿到每壹個元素,就需要循環遍歷。

如下案例加以說明:

# 壹個列表xiaoke=[2,3,4,5]# 生成器generator,類似於list,但是是把[]改為()gen=(a for a in xiaoke)for i in gen:

print(i)#結果是:2345# 為什麽要使用生成器?因為效率。# 使用生成器表達式取代列表推導式可以同時節省 cpu 和 內存(RAM)。# 如果妳構造壹個列表(list)的目的僅僅是傳遞給別的函數,# 比如 傳遞給tuple()或者set(), 那就用生成器表達式替代吧!# 本案例是直接把列表轉化為元組kk=tuple(a for a in xiaoke)

print(kk)#結果是:(2, 3, 4, 5)# python內置的壹些函數,可以識別這是生成器表達式,外面有壹對小括號,就是生成器result1=sum(a for a in range(3))

print(result1)# 列表推導式result2=sum([a for a in range(3)])

print(result2)