本篇文章簡單談談可迭代物件,迭代器和生成器之間的關係。
三者簡要關係圖
可迭代物件與迭代器
剛開始我認為這兩者是等同的,但後來發現並不是這樣;下面直接丟擲結論:
1)可迭代物件包含迭代器。
2)如果乙個物件擁有__iter__方法,其是可迭代物件;如果乙個物件擁有next方法,其是迭代器。
3)定義可迭代物件,必須實現__iter__方法;定義迭代器,必須實現__iter__和next方法。
你也許會問,結論3與結論2是不是有一點矛盾?既然乙個物件擁有了next方法就是迭代器,那為什麼迭代器必須同時實現兩方法呢?
因為結論1,迭代器也是可迭代物件,因此迭代器必須也實現__iter__方法。
介紹一下上面涉及到的兩個方法:
1)iter()
該方法返回的是當前物件的迭代器類的例項。因為可迭代物件與迭代器都要實現這個方法,因此有以下兩種寫法。
寫法一:用於可迭代物件類的寫法,返回該可迭代物件的迭代器類的例項。
寫法二:用於迭代器類的寫法,直接返回self(即自己本身),表示自身即是自己的迭代器。
也許有點暈,沒關係,下面會給出兩寫法的例子,我們結合具體例子看。
2)next()
返回迭代的每一步,實現該方法時注意要最後超出邊界要丟擲stopiteration異常。
下面舉個可迭代物件與迭代器的例子:
[python] view plain copy
#!/usr/bin/env python
class mylist(object): # 定義可迭代物件類
def __init__(self, num):
self.data = num # 上邊界
def __iter__(self):
return mylistiterator(self.data) # 返回該可迭代物件的迭代器類的例項
class mylistiterator(object): # 定義迭代器類,其是mylist可迭代物件的迭代器類
def __init__(self, data):
self.data = data # 上邊界
self.now = 0 # 當前迭代值,初始為0
def __iter__(self):
return self # 返回該物件的迭代器類的例項;因為自己就是迭代器,所以返回self
def next(self): # 迭代器類必須實現的方法
while self.now < self.data:
self.now += 1
return self.now - 1 # 返回當前迭代值
raise stopiteration # 超出上邊界,丟擲異常
my_list = mylist(5) # 得到乙個可迭代物件
print type(my_list) # 返回該物件的型別
my_list_iter = iter(my_list) # 得到該物件的迭代器例項,iter函式在下面會詳細解釋
print type(my_list_iter)
for i in my_list: # 迭代
print i
#!/usr/bin/env python12
345coding=utf-8
class mylist(object): # 定義可迭代物件類
definit(self, num):
self.data = num # 上邊界
defiter(self):
return mylistiterator(self.data) # 返回該可迭代物件的迭代器類的例項12
345class mylistiterator(object): # 定義迭代器類,其是mylist可迭代物件的迭代器類
definit(self, data):
self.data = data # 上邊界
self.now = 0 # 當前迭代值,初始為0
defiter(self):
return self # 返回該物件的迭代器類的例項;因為自己就是迭代器,所以返回self
def next(self): # 迭代器類必須實現的方法
while self.now < self.data:
self.now += 1
return self.now - 1 # 返回當前迭代值
raise stopiteration # 超出上邊界,丟擲異常12
3456
78910
1112
my_list = mylist(5) # 得到乙個可迭代物件
print type(my_list) # 返回該物件的型別
my_list_iter = iter(my_list) # 得到該物件的迭代器例項,iter函式在下面會詳細解釋
print type(my_list_iter)
for i in my_list: # 迭代
print i
執行結果:
問題:上面的例子**現了iter函式,這是什麼東西?和iter方法有關係嗎?
其實該函式與迭代是息息相關的,通過在python命令列中列印「help(iter)」得知其有以下兩種用法。
用法一:iter(callable, sentinel)
不停的呼叫callable,直至其的返回值等於sentinel。其中的callable可以是函式,方法或實現了call方法的例項。
用法二:iter(collection)
1)用於返回collection物件的迭代器例項,這裡的collection我認為表示的是可迭代物件,即該物件必須實現iter方法;事實上iter函式與iter方法聯絡非常緊密,iter()是直接呼叫該物件的iter(),並把iter()的返回結果作為自己的返回值,故該用法常被稱為「建立迭代器」。
2)iter函式可以顯示呼叫,或當執行「for i in obj:」,python直譯器會在第一次迭代時自動呼叫iter(obj),之後的迭代會呼叫迭代器的next方法,for語句會自動處理最後丟擲的stopiteration異常。
通過上面的例子,相信對可迭代物件與迭代器有了更具體的認識,那麼生成器與它們有什麼關係呢?下面簡單談一談
生成器生成器是一種特殊的迭代器,生成器自動實現了「迭代器協議」(即__iter__和next方法),不需要再手動實現兩方法。
生成器在迭代的過程中可以改變當前迭代值,而修改普通迭代器的當前迭代值往往會發生異常,影響程式的執行。
看乙個生成器的例子:
[python] view plain copy
#!/usr/bin/env python
def mylist(num): # 定義生成器
now = 0 # 當前迭代值,初始為0
while now < num:
val = (yield now) # 返回當前迭代值,並接受可能的send傳送值;yield在下面會解釋
now = now + 1 if val is none else val # val為none,迭代值自增1,否則重新設定當前迭代值為val
my_list = mylist(5) # 得到乙個生成器物件
print my_list.next() # 返回當前迭代值
print my_list.next()
my_list.send(3) # 重新設定當前的迭代值
print my_list.next()
print dir(my_list) # 返回該物件所擁有的方法名,可以看到__iter__與next在其中
#!/usr/bin/env python12
345coding=utf-8
def mylist(num): # 定義生成器
now = 0 # 當前迭代值,初始為0
while now < num:
val = (yield now) # 返回當前迭代值,並接受可能的send傳送值;yield在下面會解釋
now = now + 1 if val is none else val # val為none,迭代值自增1,否則重新設定當前迭代值為val
my_list = mylist(5) # 得到乙個生成器物件
print my_list.next() # 返回當前迭代值
print my_list.next()
my_list.send(3) # 重新設定當前的迭代值
print my_list.next()
print dir(my_list) # 返回該物件所擁有的方法名,可以看到iter與next在其中
執行結果:
具有yield關鍵字的函式都是生成器,yield可以理解為return,返回後面的值給呼叫者。不同的是return返回後,函式會釋放,而生成器則不會。在直接呼叫next方法或用for語句進行下一次迭代時,生成器會從yield下一句開始執行,直至遇到下乙個yield。
可迭代物件和迭代器
建立這個物件的類中是否定義了 iter 方法,如果定義了,那麼這個物件就是可迭代物件。isinstance obj,iterable 判斷 判斷乙個物件是不是迭代器的時候,需要判斷建立這個例項物件的類中是否定義了 iter 方法和 next 方法,如果都定義了,那麼這個物件就是可迭代物件。所以如果乙...
可迭代物件和迭代器
實現了 iter 方法的物件稱為可迭代物件,在python中,可迭代物件有字串 列表 元組 字典 集合等 class mynumbers def init self self.a 1 def iter self return self my numbers mynumbers 判斷物件是否是可迭代物...
可迭代物件和迭代器
迭代器即迭代的工具,那什麼是迭代呢?迭代是乙個重複的過程,每次重複即一次迭代,並且每次迭代的結果都是下一次迭代的初始值 while true 只是單純地重複,因而不是迭代 print l 1,2,3 count 0 while count len l 迭代 print l count count 1...