python的迭代器與生成器例項詳解

2021-09-11 16:56:11 字數 4865 閱讀 9402

本文以例項詳解了python的迭代器與生成器,具體如下所示:

1. 迭代器概述:

迭代器是訪問集合元素的一種方式。迭代器物件從集合的第乙個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會後退,不過這也沒什麼,因為人們很少在迭代途中往後退。

1.1 使用迭代器的優點

對於原生支援隨機訪問的資料結構(如tuple、list),迭代器和經典for迴圈的索引訪問相比並無優勢,反而丟失了索引值(可以使用內建函式enumerate()找回這個索引值)。但對於無法隨機訪問的資料結構(比如set)而言,迭代器是唯一的訪問元素的方式。

另外,迭代器的一大優點是不要求事先準備好整個迭代過程中所有的元素。迭代器僅僅在迭代到某個元素時才計算該元素,而在這之前或之後,元素可以不存在或者被銷毀。這個特點使得它特別適合用於遍歷一些巨大的或是無限的集合,比如幾個g的檔案,或是斐波那契數列等等。

迭代器更大的功勞是提供了乙個統一的訪問集合的介面,只要定義了__iter__()方法物件,就可以使用迭代器訪問。

迭代器有兩個基本的方法

__iter__方法:返回迭代器物件本身

下面用生成斐波那契數列為例子,說明為何用迭代器

示例**1

def fab(max): 

n, a, b = 0, 0, 1 

while n < max: 

print b 

a, b = b, a + b  

n = n + 1

直接在函式fab(max)中用print列印會導致函式的可復用性變差,因為fab返回none。其他函式無法獲得fab函式返回的數列。

示例**2

def fab(max): 

l = 

n, a, b = 0, 0, 1 

while n < max: 

a, b = b, a + b  

n = n + 1

return l

**2滿足了可復用性的需求,但是占用了記憶體空間,最好不要。

示例**3

對比:

for i in range(1000): pass

for i in xrange(1000): pass

前乙個返回1000個元素的列表,而後乙個在每次迭代中返回乙個元素,因此可以使用迭代器來解決復用可佔空間的問題

class fab(object): 

def __init__(self, max): 

self.max = max 

self.n, self.a, self.b = 0, 0, 1 

def __iter__(self): 

return self 

def next(self): 

if self.n < self.max: 

r = self.b 

self.a, self.b = self.b, self.a + self.b  

self.n = self.n + 1 

return r 

raise stopiteration()

執行

>>> for key in fabs(5): 

print key

fabs 類通過 next() 不斷返回數列的下乙個數,記憶體占用始終為常數  

1.2 使用迭代器

使用內建的工廠函式iter(iterable)可以獲取迭代器物件:

>>> lst = range(5)

>>> it = iter(lst)

>>> it

>>> it.next() 

>>> it.next() 

>>> it.next()

python處理迭代器越界是丟擲stopiteration異常

>>> it.next()

>>> it.next

>>> it.next()

traceback (most recent call last):

file "", line 1, in it.next()

stopiteration

了解了stopiteration,可以使用迭代器進行遍歷了

lst = range(5)

it = iter(lst)

try:

while true:

val = it.next()

print val

except stopiteration: 

pass

事實上,因為迭代器如此普遍,python專門為for關鍵字做了迭代器的語法糖。在for迴圈中,python將自動呼叫工廠函式iter()獲得迭代器,自動呼叫next()獲取元素,還完成了檢查stopiteration異常的工作。如下

>>> a = (1, 2, 3, 4) 

>>> for key in a:

print key

首先python對關鍵字in後的物件呼叫iter函式迭代器,然後呼叫迭代器的next方法獲得元素,直到丟擲stopiteration異常。

1.3 定義迭代器

下面乙個例子——斐波那契數列

# -*- coding: cp936 -*-

class fabs(object):

def __init__(self,max):

self.max = max

self.n, self.a, self.b = 0, 0, 1 #特別指出:第0項是0,第1項是第乙個1.整個數列從1開始

def __iter__(self):

return self

def next(self):

if self.n < self.max:

r = self.b

self.a, self.b = self.b, self.a + self.b

self.n = self.n + 1

return r

raise stopiteration()

print fabs(5)

for key in fabs(5):

print key

結果

<__main__.fabs object at 0x01a63090>
2. 迭代器

帶有 yield 的函式在 python 中被稱之為 generator(生成器),幾個例子說明下(還是用生成斐波那契數列說明)

可以看出**3遠沒有**1簡潔,生成器(yield)既可以保持**1的簡潔性,又可以保持**3的效果

示例**4 

def fab(max):

n, a, b = 0, 0, 1

while n < max:

yield b

a, b = b, a + b 

n = n = 1

執行

>>> for n in fab(5): 

print n

簡單地講,yield 的作用就是把乙個函式變成乙個 generator,帶有 yield 的函式不再是乙個普通函式,python 直譯器會將其視為乙個 generator,呼叫 fab(5) 不會執行 fab 函式,而是返回乙個 iterable 物件!在 for 迴圈執行時,每次迴圈都會執行 fab 函式內部的**,執行到 yield b 時,fab 函式就返回乙個迭代值,下次迭代時,**從 yield b 的下一條語句繼續執行,而函式的本地變數看起來和上次中斷執行前是完全一樣的,於是函式繼續執行,直到再次遇到 yield。看起來就好像乙個函式在正常執行的過程中被 yield 中斷了數次,每次中斷都會通過 yield 返回當前的迭代值。

也可以手動呼叫 fab(5) 的 next() 方法(因為 fab(5) 是乙個 generator 物件,該物件具有 next() 方法),這樣我們就可以更清楚地看到 fab 的執行流程:

>>> f = fab(3)

>>> f.next()

>>> f.next()

>>> f.next()

>>> f.next()

traceback (most recent call last):

file "", line 1, in f.next()

stopiteration

return作用

在乙個生成器中,如果沒有return,則預設執行到函式完畢;如果遇到return,如果在執行過程中 return,則直接丟擲 stopiteration 終止迭代。例如

>>> s = fab(5)

>>> s.next()

>>> s.next()

traceback (most recent call last):

file "", line 1, in s.next()

stopiteration

示例**5  檔案讀取

def read_file(fpath): 

block_size = 1024 

with open(fpath, 'rb') as f: 

while true: 

block = f.read(block_size)  

if block: 

yield block 

else: 

return

如果直接對檔案物件呼叫 read() 方法,會導致不可**的記憶體占用。好的方法是利用固定長度的緩衝區來不斷讀取檔案內容。通過 yield,我們不再需要編寫讀檔案的迭代類,就可以輕鬆實現檔案讀取。

Python生成器與迭代器

生成器只有在用的時候會出現在記憶體中,對比列表全部存在記憶體中,減少了記憶體占用 next 函式 依次取生成器的值 s x 2 for x in range 1000 中括號是列表解析,小括號表示生成一系列值,就是生成器 s at 0x7fa20aa8b048 print next s 用next ...

python 迭代器與生成器

迭代器和生成器 print 1 in 1,2,3 print 1 not in 1,2,3 print 4 in print 4 not in 1,2,3 print x not in dlkjfxfei 可迭代物件 iterable 可以被next 函式呼叫並不斷返回下乙個值 知道沒有資料時丟擲s...

Python 迭代器與生成器

一 迭代器 理解迭代器需要搞清楚容器 container 迭代器協議 可迭代物件 iterable 迭代器 iterator 生成器 generator 1 容器 container 容器是一種把多個元素組織在一起的資料結構,容器中的元素可以逐個地迭代獲取,可以用in,not in關鍵字判斷元素是否...