python 迭代器 生成器
1. 迭代器
迭代器是訪問集合元素的一種方式。迭代器物件從集合的第一個元素開始訪問,知道所有的元素被訪問完結束。迭代器只能往前不會後退,不過這也沒什麼,因為人們很少在迭代途中往後退。
1.1 使用迭代器的優點
對於原生支援隨機訪問的資料結構(如tuple、list),迭代器和經典for迴圈的索引訪問相比並無優勢,反而丟失了索引值(可以使用內建函式enumerate()找回這個索引值)。但對於無法隨機訪問的資料結構(比如set)而言,迭代器是唯一的訪問元素的方式。
另外,迭代器的一大優點是不要求事先準備好整個迭代過程中所有的元素。迭代器僅僅在迭代到某個元素時才計算該元素,而在這之前或之後,元素可以不存在或者被銷燬。這個特點使得它特別適合用於遍歷一些巨大的或是無限的集合,比如幾個G的檔案,或是斐波那契數列等等。
迭代器更大的功勞是提供了一個統一的訪問集合的介面,只要定義了__iter__()方法物件,就可以使用迭代器訪問。
迭代器有兩個基本的方法
- next方法:返回迭代器的下一個元素
- __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: L.append(b) 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 1 1 2 3 5
Fabs 類通過 next() 不斷返回數列的下一個數,記憶體佔用始終為常數
1.2 使用迭代器
使用內建的工廠函式iter(iterable)可以獲取迭代器物件:
>>> lst = range(5) >>> it = iter(lst) >>> it <listiterator object at 0x01A63110>
使用next()方法可以訪問下一個元素:
>>> it.next() 0 >>> it.next() 1 >>> it.next() 2
python處理迭代器越界是丟擲StopIteration異常
>>> it.next() 3 >>> it.next <method-wrapper 'next' of listiterator object at 0x01A63110> >>> it.next() 4 >>> it.next() Traceback (most recent call last): File "<pyshell#27>", line 1, in <module> it.next() StopIteration
瞭解了StopIteration,可以使用迭代器進行遍歷了
lst = range(5) it = iter(lst) try: while True: val = it.next() print val except StopIteration: pass
結果
>>> 0 1 2 3 4
事實上,因為迭代器如此普遍,python專門為for關鍵字做了迭代器的語法糖。在for迴圈中,Python將自動呼叫工廠函式iter()獲得迭代器,自動呼叫next()獲取元素,還完成了檢查StopIteration異常的工作。如下
>>> a = (1, 2, 3, 4) >>> for key in a: print key 1 2 3 4
首先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> 1 1 2 3 5
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 1 1 2 3 5
簡單地講,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() 1 >>> f.next() 1 >>> f.next() 2 >>> f.next() Traceback (most recent call last): File "<pyshell#62>", line 1, in <module> f.next() StopIteration
return作用
在一個生成器中,如果沒有return,則預設執行到函式完畢;如果遇到return,如果在執行過程中 return,則直接丟擲 StopIteration 終止迭代。例如
>>> s = fab(5) >>> s.next() 1 >>> s.next() Traceback (most recent call last): File "<pyshell#66>", line 1, in <module> 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,我們不再需要編寫讀檔案的迭代類,就可以輕鬆實現檔案讀取。
3. 參考
相關推薦
python~迭代器,生成器
可迭代物件: 以直接作用於 for 迴圈的資料型別有以下幾種: 一類是集合資料型別,如 list 、 tuple 、 dict 、 set 、 str 等 一類是 generator ,包括生成器和帶 yield 的generator function 這些可以直接作用於 for 迴
python~迭代器,生成器(3)
生成器 通過列表生成式,我們可以直接建立一個列表。但是,受到記憶體限制,列表容量肯定是有限的。而且,建立一個包含100萬個元素的列表,不僅佔用很大的儲存空間,如果我們僅僅需要訪問前面幾個元素,那後面絕大多數元素佔用的空間都白白浪費了。所以,如果列表元素可以按照某種演算法推算出來,那
python~迭代器,生成器(2)
**生成器一定是迭代器,但是迭代器不一定是生成器 迭代器: 可以被next()函式呼叫並不斷返回下一個值的物件稱為迭代器:Iterator ??isinstance() 判斷一個物件是否是 Iterator 物件: In [56]: from collections import I
python迭代器-生成器-列表推導式-生成器表示式-day11-12
生成器Generator 生成器函式一個包含yield關鍵字的函式就是一個生成器函式。yield可以為我們從函式中返回值,但是yield又不同於return,return的執行意味著程式的結束,呼叫生成器函式不會得到返回的具體的值,而是得到一個可迭代的物件。每一次獲取這個可
python迭代器&生成器使用技巧(1):遍歷、代理、生成器建立迭代、反向迭代
1. 手動遍歷迭代器 next() 遍歷一個可迭代物件中的所有元素,但是卻不想使用for迴圈。為了手動的遍歷可迭代物件,使用 next() 函式並在程式碼中捕獲 StopIteration 異常。 通常來講, StopIteration 用來指示迭代的結尾。 然而,如果手動
python迭代器&生成器使用技巧(2):切片、遍歷、索引值、多序列、多容器物件
1. 迭代器切片 迭代器和生成器不能使用標準的切片操作,因為它們的長度事先並不知道(並且也沒有實現索引)。 函式 islice() 返回一個可以生成指定元素的迭代器,通過遍歷並丟棄直到切片開始索引位置的所有元素,然後開始一個個的返回元素,並直到切片結束索引位置。 impo
4.python迭代器生成器裝飾器
基本概念 1.容器(container) 容器是一種把多個元素組織在一起的資料結構,容器中的元素可以逐個地迭代獲取,可以用in, not in關鍵字判斷元素是否包含在容器中。通常這類資料結構把所有的元素儲存在記憶體中(也有一些特例,並不是所有的元素都放在記憶體,比如迭代器和生成器物件)在Python中
python 迭代器 生成器
1. 迭代器 迭代器是訪問集合元素的一種方式。迭代器物件從集合的第一個元素開始訪問,知道所有的元素被訪問完結束。迭代器只能往前不會後退,不過這也沒什麼,因為人們很少在迭代途中往後退。 1.1 使用迭代器的優點 對於原生支援隨機訪問的資料結構(如tuple、list),迭代器和經典
python 迭代器 生成器 生成器表示式
生成器Generator 是建立迭代器的簡單而強大的工具。它們寫起來就像是正規的函式,需要返回資料的時候使用 yield 語句。每次 next() 被呼叫時,生成器回覆它脫離的位置(它記憶語句最後一次執行的位置和所有的資料值)。以下示例演示了生成器可以很簡單的創建出來:def reverse(data):
Python迭代器Iterator和生成器generator
容器(container) 容器是一種把多個元素組織在一起的資料結構,容器中的元素可以逐個地迭代獲取,可以用in, not in關鍵字判斷元素是否包含在容器中。通常這類資料結構把所有的元素儲存在記憶體中(也有一些特例,並不是所有的元素都放在記憶體,比如迭代器和生成器物件) 可迭代物
python迭代器、生成器和裝飾器
文章目錄 生成器 生成器表示式(generator expression) 通過使用yield關鍵字定義 迭代器 迭代器概述 iter()函式 建立迭代器 建立一個迭代器(類) 內建迭代器
python 迭代器,生成器詳解。
迭代器 任何實現了__iter__和__next__()(python2中實現next())方法的物件都是迭代器 迭代器可以被next()函式呼叫並不斷返回下一個值的,或者使用for迴圈。 因為Python的for迴圈本質上就是通過不斷呼叫next()函式實現的。 for 迴圈在處理這些
python(迭代器和生成器)
迭代器 :(列表,元組,字典,集合,字串,檔案) 迭代:每次重複的過程成為迭代的過程,每次迭代得到的結果,回作為下次迭代的初始值 迭代器:可以被next()函式呼叫並不斷返回下一個值的物件稱為迭代器 它只是實現了__next__()方法的物件,並不是容器 Iter()(iteration
3、【Python】Python 3入門(流程控制/迭代器/生成器/函式/變數作用域)
一、流程控制 1、if 控制 if 表示式1: 語句 if 表示式2: 語句 elif 表示式3: 語句 else: 語句 elif 表示式4: 語句 else: 語句 1、
Python記錄12:迭代器+生成器+生成式
'''1. 什麼是迭代器 什麼是迭代:迭代就是一個重複的過程,但是每一次重複都是基於上一次的結果而進行的 單純的重複不是迭代: while True: print(1) 迭代的過程 l=['a','b','c'] i=0 while i < len(l): pr
Python基礎【生成式 | 迭代器 | 生成器】
生成式 列表生成式 快速生成具有特定規律的列表 普通寫法:even=[]for i in range(100):if i%2==0:even.append(i) 列表生成式形式:even=[i for i in range(100) if i%2==0] ##生成0-99之間
Python 迭代物件, 迭代器, 生成器
容器 容器是一種把多個元素組織在一起的資料結構, 容器中的元素可以逐個地迭代獲取. 如: list, set, dict, tuple, str 可迭代物件 可以返回一個迭代器的物件. x = [1,2,3] y = iter(x) z = iter(x) x
python進階之 迭代器, 生成器
練習: 說出如下程式碼的列印結果 >>> def foo(): … print(111) … yield 222 … print(333) … yield 444 … print(555) >>&g
python迭代器與生成器差別
生成器是一類特殊的迭代器,在迴圈遍歷自定義容器物件時,會使用python內建函式iter()呼叫遍歷物件的_iter_(self)獲得一個迭代器,之後再迴圈對這個迭代器使用next()呼叫迭代器物件的_next_(self) 實現生成器的功能。 python中生成器和迭代器
python迭代器和生成器詳解
前文 迭代器(Iterator)和生成器(generator)是python眾多強大的資料型別之一,兩者的作用都是惰性計算,即不會立即產生所有結果,而是逐步產生一個個;兩者的區別則是生成器本質上屬於迭代器,生成器用於“憑空”生成元素,迭代器則是用於從集合中取