#原創,轉載請先聯繫app
理論性的東西有點枯燥,耐心點看~函數
1.迭代是什麼?spa
咱們知道能夠對list,tuple,dict,str等數據類型使用for...in的循環語法,從其中依次取出數據,這個過程叫作遍歷,也叫迭代。迭代是訪問集合元素的一種經常使用的方式。code
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------協程
2.可迭代對象是什麼?對象
簡單來講,能夠用for...in循環語句,從其中依次取出數據的對象,就是可迭代對象。例如,列表、元組、字典、字符串都是可迭代對象。整數、浮點數、布爾值都是不可迭代的。blog
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------字符串
3.迭代器是什麼?it
在可迭代對象進行迭代的時候,即用for...in...循環語法依次取出數據時,過程是怎樣的呢?io
咱們發現,每迭代一次(即在for...in...中每循環一次)都會返回對象中的下一條數據,一直向後讀取數據直到迭代了全部數據後結束。那麼,在這個過程當中就應該有一個「人」去記錄每次訪問到了第幾條數據,以便每次迭代均可以返回下一條數據。咱們把這個能幫助咱們進行數據迭代的「人」稱爲迭代器(Iterator)。舉個栗子,老師安排一個班的同窗每節課上課前進行演講,按學號順序進行,A同窗這節課演講,老師就會記住這節課是A同窗演講,那麼下節課就是B同窗進行演講...依次類推,在這個例子裏,老師就是一個迭代器。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4.怎樣獲取可迭代對象的迭代器?
咱們能夠經過iter()內置函數取得可迭代對象的迭代器。
list = [1,2,3,4,5] # list是可迭代對象 lterator = iter(list) # 經過iter()方法取得list的迭代器 print(lterator) 輸出: <list_iterator object at 0x7f35e6537a20>
迭代器是獲取到了,那麼應該怎樣用呢?
next()函數是經過迭代器獲取下一個位置的值。
注意: 當咱們已經迭代完最後一個數據以後,再次調用next()函數會拋出StopIteration的異常,來告訴咱們全部數據都已迭代完成,不用再執行next()函數了。
list = [1,2,3,4,5] # list是可迭代對象 lterator = iter(list) # 經過iter()方法取得list的迭代器 print(next(lterator)) # 1 print(next(lterator)) # 2 print(next(lterator)) # 3 print(next(lterator)) # 4 print(next(lterator)) # 5 print(next(lterator)) 輸出: 1 2 3 4 5 Traceback (most recent call last): File "/home/chichung/桌面/課堂練習/協程/iter方法取得可迭代對象的迭代器.py", line 8, in <module> print(next(lterator)) StopIteration
看完以爲奇怪的同窗,是否是以爲一個對象能拿出一個迭代器很amazing。好像編的同樣,別急,繼續看上去,下面有答案。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5.判斷一個對象是否可迭代
isinstance(object,classinfo)內置函數能夠判斷一個對象是不是一個已知的類型,相似 type()。
在這以前,還須要知道collections模塊裏的Iterable。通俗點講,凡是可迭代對象都是這個類的實例對象。下面來驗證一下:
import collections print(isinstance([1, 2, 3], collections.Iterable)) print(isinstance((1,2,3), collections.Iterable)) print(isinstance({"name":"chichung","age":23}, collections.Iterable)) print(isinstance("sex", collections.Iterable)) print(isinstance(123,collections.Iterable)) print(isinstance(True,collections.Iterable)) print(isinstance(1.23,collections.Iterable)) 輸出: True True True True False False False
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6.可迭代對象怎麼能夠獲取迭代器呢?
看完第4點,有些人就感受很奇怪,例如:[1,2,3]不就是一個列表,一個對象嗎?怎麼還能拿出一個迭代器來了?
首先,咱們從第5點能夠知道,可迭代對象其實都是collections模塊裏的Iterable類建立出來的實例的。你寫一個列表,覺得他不是任何類建立的,只是單純一個列表?不是的,其實它就是Iterable類建立的實例對象。點進Iterable的類看一下,你會發現新大陸。
class Iterable(metaclass=ABCMeta): __slots__ = () @abstractmethod def __iter__(self): # 注意點 while False: yield None
原來由Iterable建立的對象,是有一個魔方方法__iter__(self)的。這個方法就是返回一個迭代器的。因此,由Iterable類建立的實例對象,是能夠拿出一個迭代器的。
接下來要說的有點繞......
之因此Iterable類建立的對象是可迭代對象,是由於Iterable類有這個方法!不信?我就來編寫一個能建立可迭代對象的類。
import collections class BecomeIterable: def __iter__(self): """返回一個空的迭代器""" return None people = BecomeIterable() print(isinstance(people, collections.Iterable)) 輸出: True
騷不騷?什麼都沒有,就一個魔法方法,建立的對象就是可迭代對象了。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
7.迭代器爲何能用next()函數進行迭代?
咱們知道,能夠用iter()函數,在可迭代對象中獲取迭代器。例如:iterator = iter([1,2,3])
這樣一看,迭代器也就是一個對象而已啊,爲何他能夠用next()函數,一會兒出來一個值,一會兒又出來一個值。
實際上是這樣的,iter()函數能調用可迭代對象的魔方方法__iter__(),從而返回一個迭代器。怎麼返回的呢?__iter__()方法是使用collections模塊裏的Iterator類來建立一個迭代器對象。
接下來看下Iterator的一部分源代碼:
class Iterator(Iterable): __slots__ = () @abstractmethod def __next__(self): 'Return the next item from the iterator. When exhausted, raise StopIteration' raise StopIteration def __iter__(self): return self
是否是茅塞頓開了?和第6點的解釋原理同樣。這裏就不詳細解釋了。稍微注意下魔方方法__next__()的最後一句,若是超出迭代方位就拋出StopIteration異常。
還有一點須要注意,迭代器的源代碼也有__iter__()魔方方法,因此,Iterator也是一個可迭代對象呀!!!
因此,若是你喜歡在迭代器裏面再取出迭代器也是能夠的,可是好像有點無聊......目前還不知道有什麼應用到......
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
8.建立一個迭代器類
理論講完了額...不懂的仍是要多看幾遍。下面開始應用~
若是咱們編寫一段代碼,想把結果一個一個迭代出來,這時候就須要編寫迭代器類了。
class MyIterator(): def __init__(self): self.list = [] self.position = 0 def add_name(self,name): self.list.append(name) def __iter__(self): return self # 返回一個迭代器 def __next__(self): if self.position < len(self.list): item = self.list[self.position] self.position += 1 return item else: raise StopIteration people = MyIterator() # people對象既是一個迭代器,也是一個可迭代對象 people.add_name("張三") people.add_name("李四") people.add_name("王五") # 把people當作一個迭代器來看時 print(next(people)) print(next(people)) print(next(people)) # 把humen當作一個可迭代對象來看時 humen = MyIterator() # 由於迭代器只能用一次,再用會拋出錯誤,因此須要再建立 humen.add_name("張三") humen.add_name("李四") humen.add_name("王五") iterator = iter(humen) # iter()方法獲取可迭代對象的迭代器 print(next(iterator)) print(next(iterator)) print(next(iterator))
輸出:
張三
李四
王五
張三
李四
王五
注意看註釋,若是原理都懂,這實際上是一個很簡單的例子。