Python迭代器,可迭代物件,生成器
1. 迭代器
迭代器是訪問集合元素的一種方式。迭代器物件從集合的第一個元素開始訪問,知道所有的元素被訪問完結束。迭代器只能往前不會後退,不過這也沒什麼,因為人們很少在迭代途中往後退。
1.1 使用迭代器的優點
對於原生支援隨機訪問的資料結構(如tuple、list),迭代器和經典for迴圈的索引訪問相比並無優勢,反而丟失了索引值(可以使用內建函式enumerate()找回這個索引值)。但對於無法隨機訪問的資料結構(比如set)而言,迭代器是唯一的訪問元素的方式。
另外,迭代器的一大優點是不要求事先準備好整個迭代過程中所有的元素。迭代器僅僅在迭代到某個元素時才計算該元素,而在這之前或之後,元素可以不存在或者被銷燬。這個特點使得它特別適合用於遍歷一些巨大的或是無限的集合,比如幾個G的檔案,或是斐波那契數列等等。
迭代器更大的功勞是提供了一個統一的訪問集合的介面,只要定義了iter迭代器有兩個基本的方法
next
方法:返回迭代器的下一個元素__iter__
方法:返回迭代器物件本身
下面用生成斐波那契數列為例子,說明為何用迭代器
#程式碼1:直接在函式fab(max)中用print列印會導致函式的可複用性變差,因為fab返回None。其他函式無法獲得fab函式返回的數列。
def fab(max):
n, a, b = 0, 0, 1
while n < max:
print b
a, b = b, a + b
n = n + 1
#程式碼2:程式碼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
#程式碼3:
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,我們不再需要編寫讀檔案的迭代類,就可以輕鬆實現檔案讀取。
#
#
#
#
#
#
#
http://www.cnblogs.com/wswang/p/6047994.html
也就是說迭代器類似於一個遊標,卡到哪裡就是哪裡,可以通過這個來訪問某個可迭代物件的元素;同時,也不是隻有Python有這個特性。比如C++的STL中也有這個,如vector::iterator it。下面主要說一下Python中的可迭代物件和迭代器吧。
- Python可迭代物件(Iterable)
Python中經常使用for
來對某個物件進行遍歷,此時被遍歷的這個物件就是可迭代物件,像常見的list
,tuple
都是。如果給一個準確的定義的話,就是隻要它定義了可以返回一個迭代器的__iter__
方法,或者定義了可以支援下標索引的__getitem__
方法(這些雙下劃線方法會在其他章節中全面解釋),那麼它就是一個可迭代物件。 - Python迭代器(iterator)
迭代器是通過next()
來實現的,每呼叫一次他就會返回下一個元素,當沒有下一個元素的時候返回一個StopIteration
異常,所以實際上定義了這個方法的都算是迭代器。可以用通過下面例子來體驗一下迭代器:
In [38]: s = 'ab'
In [39]: it = iter(s)
In [40]: it
Out[40]: <iterator at 0x1068e6d50>
In [41]: print it
<iterator object at 0x1068e6d50>
In [42]: it.next()
Out[42]: 'a'
In [43]: it.next()
Out[43]: 'b'
In [44]: it.next()
---------------------------------------------------------------------------
StopIteration Traceback (most recent call last)
<ipython-input-44-54f0920595b2> in <module>()
----> 1 it.next()
StopIteration:
自己實現一個迭代器,如下(參見官網文件):
class Reverse:
"""Iterator for looping over a sequence backwards."""
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def next(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
rev = Reverse('spam')
for char in rev:
print char
[output]
m
a
p
s
- 生成器(Generators)
生成器是構造迭代器的最簡單有力的工具,與普通函式不同的只有在返回一個值的時候使用yield
來替代return
,然後yield
會自動構建好next()
和iter()
。是不是很省事。例如:
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
>>> for char in reverse('golf'):
... print char
...
f
l
o
g
生成器最佳應用場景是:你不想同一時間將所有計算出來的大量結果集分配到記憶體當中,特別是結果集裡還包含迴圈。比方說,迴圈列印1000000個數,我們一般會使用xrange()而不是range(),因為前者返回的是生成器,後者返回的是列表(列表消耗大量空間)。
相關推薦
搞清楚 Python 的迭代器、可迭代物件、生成器
很多夥伴對 Python 的迭代器、可迭代物件、生成器這幾個概念有點搞不清楚,我來說說我的理解,希望對需要的朋友有所幫助。 1 迭代器協議 迭代器協議是核心,搞懂了這個,上面的幾個概念也就很好理解了。 所謂迭代器協議,就是要求一個迭代器必須要實現如下兩個方法 iterator.__iter__(
python迭代器和可迭代物件
迭代器 定義:能夠使用for-in進行遍歷,並且能夠使用next依次獲取其中一個元素。 說明: 生成器就是一種特殊的迭代器 判斷一個物件是不是迭代器 from collections import Iterator # lt
Python:迭代器、可迭代物件、生成器
1、什麼叫迭代 現在,我們已經獲得了一個新線索,有一個叫做“可迭代的”概念。 首先,我們從報錯來分析,好像之所以1234不可以for迴圈,是因為它不可迭代。那麼如果“可迭代”,就應該可以被for迴圈了。 這個我們知道呀,字串、列表、元組、字典、集合都可以被for迴圈,說明他們都是可迭代的
Python 中 生成器、迭代器、可迭代物件 的概念
生成器 在 Python 中,一邊迴圈一邊計算的機制,稱為 生成器(generator) 可以通過 next() 函式獲得 generator 的下一個返回值 生成器 的兩種表示方法: 1、將列表生成式的 [ ] 改為 ( ) [2*x for x
迭代器和可迭代物件
基於python3 迭代器 = 可迭代的物件 可迭代的物件 != 迭代器 講在前面: 返回迭代器的物件,有:open(), map(), zip()和filte()函式,這幾個函式直接返回迭代器也就是可以直接在結果中呼叫next 如: f = open('xxx.txt')
迭代器、可迭代物件、生成器
迭代器與可迭代物件 1、定義: 可迭代物件:大部分容器如 list,truples,str,sets是可迭代物件,但是他們不是迭代器。可迭代物件實現了__iter__方法,返回一個迭代器,或者使用iter(“可迭代物件”)返回一個迭代器。 迭代器:迭代器提供了一
【ES6】迭代器與可迭代物件
ES6 新的陣列方法、集合、for-of 迴圈、展開運算子(...)甚至非同步程式設計都依賴於迭代器(Iterator )實現。本文會詳解 ES6 的迭代器與生成器,並進一步挖掘可迭代物件的內部原理與使用方法 一、迭代器的原理 在程式語言中處理陣列或集合時,使用迴圈語句必須要初始化一個變數記錄迭
列表解析式、生成器、迭代器及可迭代物件的區別和應用
導文 語法糖(Syntactic sugar) 列表生成式(list comprehension) 生成器(generator) 迭代器(iterator) 可迭代物件(iterable) Iterable、Iterator與Generator之間的關係
python 叠代器與可叠代對象
try 而且 clas style 是我 ble 但是 加載 instance 叠代器一定是可叠代對象,但是可叠代對象不一定是叠代器。 list,truple,str這些都是可叠代對象,但是他們不一定是叠代器。叠代器本身不知道自己要執行多少次,所以可以理解為不知道有多少個
python的生成器與叠代器和可叠代對象
但是 class 進行 避免異常 示例代碼 iterable 打印 iterator 同時 來簡單的說下python中的生成器和可叠代對象以及叠代器的問題。只是簡單地記錄一下並不涉及太深入的內容。 首先來說一下什麽是生成器,先看下面的代碼: 1 #_*_ coding:u
叠代器_可叠代對象_生成器
port yield iter() als ins typeerror tor list collect [可叠代對象]保存的是已經生成好的數據,占用大量的空間有__iter__方法 就是可叠代對象(Iterable) [叠代器]保存的是生成數據的方法,占用極小的空間,需
叠代器、可叠代對象與生成器
for instance ron 地方 我們 app ont generator 大數據 Iterator 與 gerater的作用是優化內存,當處理大文件,大數據的時候可以使用。 1. 對大列表進行優化 2. 大文件的優化 一、基本概念 叠代器: 一種數
python的迭代器,可迭代物件,生成器理解
上篇文章, python itertools 裡面實現的groupby方法。裡面用到了object, id, iter等很基礎的方法, 看的有點暈。這裡重新整理一下迭代器,可迭代物件, 生成器。複習一下,加深印象。 python語言很容易上手。比如for迴圈。 a = [1, 2,
python中的生成器、迭代器,可迭代物件
最近學習了python中的生成器、迭代器、可迭代物件的知識,現在回顧一下,鞏固理解 先說一下列表生成式: 執行結果如下: 通過方括號加入裡面的表示式,從而生成一個列表,在這裡注意一下,列表生成時也可以加入函式: 結果如下: 計算了X的三次方
python迭代,可迭代物件,生成器,迭代器--
python迭代 給定一個list或tuple,我們可以通過for迴圈來遍歷這個list或tuple,這種遍歷我們稱為迭代(Iteration) 可迭代物件: List:for a in List dict:(因為dict的儲存不是按照list的方式順序
Python迭代器,可迭代物件,生成器
1. 迭代器 迭代器是訪問集合元素的一種方式。迭代器物件從集合的第一個元素開始訪問,知道所有的元素被訪問完結束。迭代器只能往前不會後退,不過這也沒什麼,因為人們很少在迭代途中往後退。 1.1 使用迭代器的優點 對於原生支援隨機訪問的資料結構(
迭代器,可迭代物件,生成器區別
迭代物件 :實現__iter__方法,返回迭代器。不需要顯示繼承Iterable, 迭代器: 實現_iter__方法,__next__方法,不需要顯示繼承Iterator from collections import Iterable,Iterator def generator():
Pythoh 迭代器,可迭代物件,容器,生成器
容器一般都是可迭代物件,是一種資料結構(data structure)。很多容器(list,dict,tuple)都是可迭代物件。但是可迭代物件不一定是一種資料結構,比如開啟的檔案或者sockets。可迭代物件可以(can)返回迭代器。每一個可迭代物件在程式碼都實現了__it
Python3學習(8)--迭代,可迭代的和迭代器
開始本篇之前,我們先來了解幾個單詞 迭代:iteration 可迭代的:Iterable 迭代器:iterator 從單詞我們可以看出來差異,可迭代的一看就是狀態詞,我們不做多說,下面會再講,而我們發現迭代和迭代器都是一個名詞表示,只不過迭代相比較
list的迭代器能解決併發問題,collection 的迭代器不能解決併發問題,for可以解決併發問題
list的迭代器能解決併發問題,collection 的迭代器不能解決併發問題 為什麼list支援add,collection不支援 例如有兩個人同時新增第三個元素 list的迭代器能鎖定執行緒 只有等第一人新增完成才能進行第二個人新增 而 collection的迭代器卻不