for 循環 是咱們在 Python 裏很是經常使用的一個語法,但你有沒有思考過 for 循環是怎樣實現的?編程
若是你之前接觸過 C++,應該會知道相似 for (int i = 0; i < 100; i++)
這樣的寫法,它定義了 循環的執行條件 i < 100
以及 每次循環結束後執行的語句 i++
,而 for
自己只起到讓代碼重複執行的做用,並無什麼額外的功能。這在 Python 中其實更像是 while 循環:函數
i = 0 while i < 100: # 執行循環代碼 i += 1
但 Python 裏的 for 循環卻不同。使用 for
時,咱們沒有額外指定結束條件,也不須要一個用來計數的數值,甚至能夠經過一個字符串進行循環。之因此能夠這樣,是由於 Python 中的 迭代器(Iterator) 以及 可迭代對象(Iterable) 。人工智能
若是一個對象定義了 __iter__
和 __next__
兩個方法, 它就是一個迭代器 。對於迭代器來講,__iter__
返回的是它自身 self ,__next__
則是 返回迭代器中的下一個值 ,若是沒有值了則拋出一個 StopIteration
的異常。關於這點,你能夠想象成一個只進不退的標記位,每次調用 __next__
,就會將標記日後移一個元素並返回,直到結束。spa
有了迭代器的概念以後,若是一個對象定義了 __iter__
和方法,返回一個迭代器對象,那麼 它就是一個可迭代的對象 。code
從表現上來講,一個對象 可迭代 ,那麼它就能夠被 for 循環使用。好比咱們常常用到的 list、dict、str 等類型,都是可迭代的,因此也就能夠經過 for 循環進行遍歷,或者更準確的說:被迭代。對象
有一點繞,咱們再來理一理迭代器(Iterator)和可迭代(Iterable)這兩個的差異:繼承
__iter__
方法。反過來則不成立。(事實上,Iterator 就是 Iterable 的子類)__iter__
方法 返回的是自身,並不產生新實例 。而可迭代對象的 __iter__
方法一般會生成一個新的迭代器對象。__iter__
、__next__
分別對應於 Python 的內置函數 iter()
和 next()
:好比 iter(aList)
就至關於 aList.__iter__()
。遞歸
因此關於上述兩點,咱們能夠有如下的例子來驗證:ci
迭代器和可迭代之間的繼承關係。rem
__iter__
方法返回值的區別。id 相同表明是同一個實例。
明白了上述的概念以後,for 循環的實現就好理解了:
__iter__
方法,獲取相應的迭代器__next__
方法的返回值賦值給循環變量StopIteration
異常,循環結束再來看個例子:
思考題: 想想爲何迭代器 aListIter 被 for 循環迭代第二次的時候就沒有輸出了?
既然 __next__
方法能夠本身定義,咱們也能夠本身實現一個迭代器。好比要 輸出一個斐波那契數列 (每一位數值都是前兩位數值之和,原題回覆關鍵字 906 ),一般的作法是循環,「高級」一點的作法是遞歸。但咱們也能夠直接寫一個斐波那契迭代器:
# 定義迭代器 class Fibonacci(): def __init__(self): self.a = 0 self.b = 1 def __iter__(self): return self def __next__(self): # 結束條件 if self.b > 100: raise StopIteration # 更新一次數值 self.a, self.b = self.b, self.a + self.b return self.a # 建立迭代器 fib = Fibonacci() # 進行迭代 for f in fib: print(f, end=' ')
輸出:
1 1 2 3 5 8 13 21 34 55 89
這個例子中,咱們並無保存一個序列,只是定義了一種規則,就也能夠被迭代。
使用迭代器的好處在於:它是一種 延遲操做 ,即當須要用到的時候纔去產生結果。好比對於一個序列來講,若是咱們要遍歷它,並不須要再一開始就把全部元素都生成好,而是隻須要知道每一個元素的下一個元素是什麼就能夠了。這樣能夠節省不少空間,尤爲對於數量很大的集合來講。
若是你不懂迭代器的概念,並不影響在代碼中使用 for 循環。但瞭解以後,你會對代碼理解得更透徹,同時這也是爲咱們後面要講到的 生成器 作鋪墊。
════
其餘文章及回答:
如何自學Python | 新手引導 | 精選Python問答 | Python單詞表 | 人工智能 | 爬蟲 | 我用Python | requests | 計算機視覺 | 字符播放器 | 一圖學Python
歡迎搜索及關注公衆號: Crossin的編程教室