Python進階——迭代器和可迭代對象有什麼區別?

{"type":"doc","content":[{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"閱讀本文大約需要 12 分鐘。","attrs":{}}]}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 Python 開發中,我們經常聽到有關「容器」、「迭代器」、「可迭代對象」、「生成器」的概念。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們經常把這些概念搞混淆,它們之間有哪些聯繫和區別呢?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這篇文章,我們就來看一下它們之間的關係。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"容器","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"首先,我們先來看一下容器是如何定義的?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"簡單來說,容器就是存儲某些元素的統稱,它最大的特性就是判斷一個元素是否在這個容器內。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"怎麼理解這句話?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"很簡單,在 Python 中,我們通常使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"in","attrs":{}}],"attrs":{}},{"type":"text","text":" 或 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"not in","attrs":{}}],"attrs":{}},{"type":"text","text":" 來判斷一個元素存在/不存在於一個容器內。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"例如下面這個例子:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"print('x' in 'xyz') # True\nprint('a' not in 'xyz') # True\nprint(1 in [1, 2, 3]) # True\nprint(2 not in (1, 2, 3)) # False\nprint('x' not in {'a', 'b', 'c'}) # True\nprint('a' in {'a': 1, 'b': 2}) # True","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這個例子中,我們可以看到 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"str","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"list","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"tuple","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"set","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"dict","attrs":{}}],"attrs":{}},{"type":"text","text":" 都可以通過 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"in","attrs":{}}],"attrs":{}},{"type":"text","text":" 或 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"not in","attrs":{}}],"attrs":{}},{"type":"text","text":" 來判斷一個元素是否在存在/不存在這個實例中,所以這些類型我們都可以稱作「容器」。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那爲什麼這些「容器」可以使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"in","attrs":{}}],"attrs":{}},{"type":"text","text":" 或 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"not in","attrs":{}}],"attrs":{}},{"type":"text","text":" 來判斷呢?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這是因爲它們都實現了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__contains__","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我們也想自定義一個容器,只需像下面這樣,在類中定義 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__contains__","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法就可以了:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"class A:\n\n def __init__(self):\n self.items = [1, 2]\n\n def __contains__(self, item):\n return item in self.items\n\na = A()\nprint(1 in a) # True\nprint(2 in a) # True\nprint(3 in a) # False","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這個例子中,類 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"A","attrs":{}}],"attrs":{}},{"type":"text","text":" 定義了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__contains__","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法,所以我們就可以使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"1 in a","attrs":{}}],"attrs":{}},{"type":"text","text":" 的方式去判斷這個元素是否在 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"A","attrs":{}}],"attrs":{}},{"type":"text","text":" 這個容器內。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"換句話說,一個類只要實現了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__contains__","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法,那麼它就是一個「容器」。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們在開發時,除了使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"in","attrs":{}}],"attrs":{}},{"type":"text","text":" 判斷元素是否在容器內之外,另外一個常用的功能是:輸出容器內的所有元素。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"例如執行 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"for x in [1, 2, 3]","attrs":{}}],"attrs":{}},{"type":"text","text":",就可以迭代出容器內的所有元素。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"那使用這種方式輸出元素,是如何實現的?這就跟「迭代器」有關","attrs":{}}]},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"迭代器","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"一個對象要想使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"for","attrs":{}}],"attrs":{}},{"type":"text","text":" 的方式迭代出容器內的所有數據,這就需要這個類實現「迭代器協議」。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也就是說,一個類如果實現了「迭代器協議」,就可以稱之爲「迭代器」。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"什麼是「迭代器協議」呢?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在 Python 中,實現迭代器協議就是實現以下 2 個方法:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"__iter__","attrs":{}}],"attrs":{}},{"type":"text","text":":這個方法返回對象本身,即 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"self","attrs":{}}],"attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"__next__","attrs":{}}],"attrs":{}},{"type":"text","text":":這個方法每次返回迭代的值,在沒有可迭代元素時,拋出 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"StopIteration","attrs":{}}],"attrs":{}},{"type":"text","text":" 異常","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面我們來看一個實現迭代器協議的例子:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"# coding: utf8\n\nclass A:\n \"\"\"A 實現了迭代器協議 它的實例就是一個迭代器\"\"\"\n def __init__(self, n):\n self.idx = 0\n self.n = n\n\n def __iter__(self):\n print('__iter__')\n return self\n\n def __next__(self):\n if self.idx < self.n:\n val = self.idx\n self.idx += 1\n return val\n else:\n raise StopIteration()\n\n# 迭代元素\na = A(3)\nfor i in a:\n print(i)\n# 再次迭代 沒有元素輸出 因爲迭代器只能迭代一次\nfor i in a:\n print(i)\n\n# __iter__\n# 0\n# 1\n# 2\n# __iter__","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這個例子中,我們定義了一個類 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"A","attrs":{}}],"attrs":{}},{"type":"text","text":",它內部實現了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__iter__","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"next","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其中 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__iter__","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法返回了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"self","attrs":{}}],"attrs":{}},{"type":"text","text":",","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"next","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法實現了具體的迭代細節。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"然後執行 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"a = A(3)","attrs":{}}],"attrs":{}},{"type":"text","text":",在執行 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"for i in a","attrs":{}}],"attrs":{}},{"type":"text","text":" 時,我們看到調用了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__iter__","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法,然後依次輸出 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"next","attrs":{}}],"attrs":{}},{"type":"text","text":" 中的元素。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其實在執行 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"for","attrs":{}}],"attrs":{}},{"type":"text","text":" 循環時,實際執行流程是這樣的:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"for i in a","attrs":{}}],"attrs":{}},{"type":"text","text":" 相當於執行 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"iter(a)","attrs":{}}],"attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"每次迭代時會執行一次 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__next__","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法,返回一個值","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":3,"align":null,"origin":null},"content":[{"type":"text","text":"如果沒有可迭代的數據,拋出 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"StopIteration","attrs":{}}],"attrs":{}},{"type":"text","text":" 異常,","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"for","attrs":{}}],"attrs":{}},{"type":"text","text":" 會停止迭代","attrs":{}}]}],"attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是請注意,當我們迭代完 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"for i in a","attrs":{}}],"attrs":{}},{"type":"text","text":" 時,如果再次執行迭代,將不會有任何數據輸出。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我們想每次執行都能迭代元素,只需每次迭代一個新對象即可:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"# 每次都迭代一個對象\nfor i in A(3):\n print(i)","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"可迭代對象","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"明白了「迭代器」是如何執行的,我們接着來看什麼是「可迭代對象」?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這是什麼意思?難道一個類是「迭代器」,那麼它的實例不是一個「可迭代對象」嗎? 它們之間又有什麼區別?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其實,但凡是可以返回一個「迭代器」的對象,都可以稱之爲「可迭代對象」。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"換句話說:","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"__iter__","attrs":{}}],"marks":[{"type":"strong"}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":" 方法返回一個迭代器,那麼這個對象就是「可迭代對象」。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"聽起來不太好理解,我們來看一個例子。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"class A:\n # A是迭代器 因爲它實現了 __iter__ 和__next__方法\n def __init__(self, n):\n self.idx = 0\n self.n = n\n\n def __iter__(self):\n return self\n\n def __next__(self):\n if self.idx < self.n:\n val = self.idx\n self.idx += 1\n return val\n else:\n raise StopIteration()\n\nclass B:\n # B不是迭代器 但B的實例是一個可迭代對象\n # 因爲它只實現了 __iter__\n # __iter__返回了A的實例 迭代細節交給了A\n def __init__(self, n):\n self.n = n\n\n def __iter__(self):\n return A(self.n)\n\n# a是一個迭代器 同時也是一個可迭代對象\na = A(3)\nfor i in a:\n print(i)\n# <__main__.a object="" at="">\nprint(iter(a))\n\n# b不是迭代器 但它是可迭代對象 因爲它把迭代細節交給了A\nb = B(3)\nfor i in b:\n print(i)\n# <__main__.a object="" at="">\nprint(iter(b))","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"仔細看這個例子,我們定義了 2 個類 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"A","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"B","attrs":{}}],"attrs":{}},{"type":"text","text":",","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"A","attrs":{}}],"attrs":{}},{"type":"text","text":" 實現了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"iter","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"next","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"而 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"B","attrs":{}}],"attrs":{}},{"type":"text","text":" 只實現了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__iter__","attrs":{}}],"attrs":{}},{"type":"text","text":",並沒有實現 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__next__","attrs":{}}],"attrs":{}},{"type":"text","text":",而且它的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"iter","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回值是一個 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"A","attrs":{}}],"attrs":{}},{"type":"text","text":" 的實例。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"A","attrs":{}}],"attrs":{}},{"type":"text","text":" 來說:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"A","attrs":{}}],"attrs":{}},{"type":"text","text":" 是一個「迭代器」,因爲其實現了迭代器協議 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__iter__","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"next","attrs":{}}],"attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"同時 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"A","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__iter__","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法返回了實例本身 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"self","attrs":{}}],"attrs":{}},{"type":"text","text":",也就是說返回了一個迭代器,所以 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"A","attrs":{}}],"attrs":{}},{"type":"text","text":" 的實例 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"a","attrs":{}}],"attrs":{}},{"type":"text","text":" 也是一個「可迭代對象」","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對於","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"B","attrs":{}}],"attrs":{}},{"type":"text","text":" 來說:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"B","attrs":{}}],"attrs":{}},{"type":"text","text":" 不是一個「迭代器」,因爲它只了實現 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__iter__","attrs":{}}],"attrs":{}},{"type":"text","text":",沒有實現 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"next","attrs":{}}],"attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由於 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"B","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__iter__","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"A","attrs":{}}],"attrs":{}},{"type":"text","text":" 的實例,而 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"A","attrs":{}}],"attrs":{}},{"type":"text","text":" 是一個迭代器,所以 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"B","attrs":{}}],"attrs":{}},{"type":"text","text":" 的實例 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"b","attrs":{}}],"attrs":{}},{"type":"text","text":" 是一個「可迭代對象」,","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"換句話說,","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"B","attrs":{}}],"marks":[{"type":"strong"}],"attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":" 把迭代細節交給了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"A","attrs":{}}],"marks":[{"type":"strong"}],"attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總之,一個類的迭代細節,是可以交給另一個類的,就像這個例子的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"B","attrs":{}}],"attrs":{}},{"type":"text","text":" 這樣,所以 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"B","attrs":{}}],"attrs":{}},{"type":"text","text":" 的實例只能是「可迭代對象」,而不是「迭代器」。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其實,這種情況我們見的非常多,我們使用最多的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"list","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"tuple","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"set","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"dict","attrs":{}}],"attrs":{}},{"type":"text","text":" 類型,都只是「可迭代對象」,但不是「迭代器」,因爲它們都是把迭代細節交給了另外一個類,這個類纔是真正的迭代器。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"看下面這個例子,你就能明白這兩者之間的差別了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"# list 是可迭代對象\n>>> l = [1, 2]\n# list 的迭代器是 list_iterator\n>>> iter(l)\n\n# 執行的是 list_iterator 的 __next__\n>>> iter(l).__next__()\n>>> 1\n\n# tuple 是可迭代對象\n>>> t = ('a', 'b')\n# tuple 的迭代器是 tuple_iterator\n>>> iter(t)\n\n# 執行的是 tuple_iterator 的 __next__\n>>> iter(t).__next__()\n>>> a\n\n# set 是可迭代對象\n>>> s = {1, 2}\n# set 的迭代器是 set_iterator\n>>> iter(s)\n\n# 執行的是 set_iterator 的 __next__\n>>> iter(s).__next__()\n>>> 1\n\n# dict 是可迭代對象\n>>> d = {'a': 1, 'b': 2}\n# dict 的迭代器是 dict_keyiterator\n>>> iter(d)\n# 執行的是 dict_keyiterator 的 __next__\n\n>>> iter(d).next()\n>>> a","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"以 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"list","attrs":{}}],"attrs":{}},{"type":"text","text":" 類型爲例,我們先定義 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"l = [1, 2]","attrs":{}}],"attrs":{}},{"type":"text","text":",然後執行 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"iter(l)","attrs":{}}],"attrs":{}},{"type":"text","text":" 得到 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"list","attrs":{}}],"attrs":{}},{"type":"text","text":" 類型的迭代器是 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"list_iterator","attrs":{}}],"attrs":{}},{"type":"text","text":",也就是說在迭代 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"list","attrs":{}}],"attrs":{}},{"type":"text","text":" 時,其實執行的是 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"list_iterator","attrs":{}}],"attrs":{}},{"type":"text","text":" 的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"next","attrs":{}}],"attrs":{}},{"type":"text","text":",","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"list","attrs":{}}],"attrs":{}},{"type":"text","text":" 把具體的迭代細節,交給了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"list_iterator","attrs":{}}],"attrs":{}},{"type":"text","text":"。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"list","attrs":{}}],"attrs":{}},{"type":"text","text":" 是一個可迭代對象,但它不是迭代器。其他類型 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"tuple","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"set","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"dict","attrs":{}}],"attrs":{}},{"type":"text","text":" 也是同樣的道理。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"由此我們可以得出一個結論:","attrs":{}},{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"迭代器一定是個可迭代對象,但可迭代對象不一定是迭代器。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"生成器","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我們再來看什麼是「生成器」?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其實,「生成器」是一個特殊的「迭代器」,並且它也是一個「可迭代對象」。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"有 2 種方式可以創建一個生成器:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"生成器表達式","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"生成器函數","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"用生成器表達式創建一個生成器的例子如下:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"# 創建一個生成器 類型是 generator\n>>> g = (i for i in range(5))\n>>> g\n at 0x101334f50>\n# 生成器就是一個迭代器\n>>> iter(g)\n at 0x101334f50>\n# 生成器也是一個可迭代對象\n>>> for i in g:\n... print(i)\n# 0 1 2 3 4","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"注意看這個例子,我們使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"g = (i for i in range(5))","attrs":{}}],"attrs":{}},{"type":"text","text":" 創建了一個生成器,它的類型是 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"generator","attrs":{}}],"attrs":{}},{"type":"text","text":",同時調用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"iter(g)","attrs":{}}],"attrs":{}},{"type":"text","text":" 可以得知 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"iter","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回的是實例本身,即生成器也是一個迭代器,並且它也是一個可迭代對象。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"再來看用函數創建一個生成器:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"def gen(n):\n for i in range(n):\n yield i\n\n# 創建一個生成器\ng = gen(5)\n# \nprint(g)\n# \nprint(type(g))\n\n# 迭代這個生成器\nfor i in g:\n print(i)\n# 0 1 2 3 4","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在這個例子中,我們在函數中使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"yield","attrs":{}}],"attrs":{}},{"type":"text","text":" 關鍵字。其實,包含 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"yield","attrs":{}}],"attrs":{}},{"type":"text","text":" 關鍵字的函數,不再是一個普通的函數,而返回的是一個生成器。它在功能上與上面的例子一樣,可以迭代生成器中的所有數據。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通常情況下,我們習慣在函數內使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"yield","attrs":{}}],"attrs":{}},{"type":"text","text":" 的方式來創建一個生成器。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但是,使用生成器迭代數據相比於普通方式迭代數據,有什麼優勢呢?","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這就要來看一下使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"yield","attrs":{}}],"attrs":{}},{"type":"text","text":" 的函數和使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"return","attrs":{}}],"attrs":{}},{"type":"text","text":" 的普通函數,有什麼區別了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"yield","attrs":{}}],"attrs":{}},{"type":"text","text":" 的函數與使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"return","attrs":{}}],"attrs":{}},{"type":"text","text":" 的函數,在執行時的差別在於:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"bulletedlist","content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"包含 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"return","attrs":{}}],"attrs":{}},{"type":"text","text":" 的方法會以 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"return","attrs":{}}],"attrs":{}},{"type":"text","text":" 關鍵字爲最終返回,每次執行都返回相同的結果","attrs":{}}]}],"attrs":{}},{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"包含 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"yield","attrs":{}}],"attrs":{}},{"type":"text","text":" 的方法一般用於迭代,每次執行時遇到 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"yield","attrs":{}}],"attrs":{}},{"type":"text","text":" 就返回 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"yield","attrs":{}}],"attrs":{}},{"type":"text","text":" 後的結果,但內部會保留上次執行的狀態,下次繼續迭代時,會繼續執行 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"yield","attrs":{}}],"attrs":{}},{"type":"text","text":" 之後的代碼,直到再次遇到 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"yield","attrs":{}}],"attrs":{}},{"type":"text","text":" 後返回","attrs":{}}]}],"attrs":{}}],"attrs":{}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當我們想得到一個集合時,如果使用普通方法,只能一次性創建出這個集合,然後 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"return","attrs":{}}],"attrs":{}},{"type":"text","text":" 返回:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"def gen_data(n):\n # 創建一個集合\n return [i for i in range(n)]","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"但如果此時這個集合中的數據非常多,我們就需要在內存中一次性申請非常大的內存空間來存儲。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我們使用 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"yield","attrs":{}}],"attrs":{}},{"type":"text","text":" 生成器的方式迭代這個集合,就能解決內存佔用大的問題:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"codeblock","attrs":{"lang":"python"},"content":[{"type":"text","text":"for gen_data(n):\n for i in range(n):\n # 每次只返回一個元素\n yield i","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"使用生成器創建這個集合,只有在迭代執行到 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"yield","attrs":{}}],"attrs":{}},{"type":"text","text":" 時,纔會返回一個元素,在這個過程中,不會一次性申請非常大的內存空間。當我們面對這種場景時,使用生成器就非常合適了。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"其實,生成器在 Python 中還有很大的用處,我會在後面的文章講解 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"yield","attrs":{}}],"attrs":{}},{"type":"text","text":" 時,再進行詳細的分析。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":1},"content":[{"type":"text","text":"總結","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"總結一下,這篇文章我們主要分析了 Python 中「容器」、「迭代器」、「可迭代對象」、「生成器」的聯繫和區別,用一張圖表示它們的關係:","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/48/486a637a99957e74aa6d47b093a5c509.png","alt":null,"title":null,"style":null,"href":null,"fromPaste":true,"pastePass":true}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果一個類實現了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__iter__","attrs":{}}],"attrs":{}},{"type":"text","text":" 和 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"__next__","attrs":{}}],"attrs":{}},{"type":"text","text":" 方法,那麼它就是一個迭代器。如果只是實現了 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"iter","attrs":{}}],"attrs":{}},{"type":"text","text":",並且這個方法返回的是一個迭代器類,那麼這個類的實例就只是一個可迭代對象,因爲它的迭代細節是交給了另一個類來處理。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"像我們經常使用的 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"list","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"tuple","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"set","attrs":{}}],"attrs":{}},{"type":"text","text":"、","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"dict","attrs":{}}],"attrs":{}},{"type":"text","text":" 類型,它們並不是迭代器,只能叫做可迭代對象,它們的迭代細節都是交給了另一個類來處理的。由此我們也得知,一個迭代器一定是一個可迭代對象,但可迭代對象不一定是迭代器。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"而生成器可以看做是一個特殊的迭代器,同時它也是一個可迭代對象。使用生成器配合 ","attrs":{}},{"type":"codeinline","content":[{"type":"text","text":"yield","attrs":{}}],"attrs":{}},{"type":"text","text":" 使用,我們可以實現懶惰計算的功能,同時,我們也可以用非常小的內存,來迭代一個大集合中的數據。","attrs":{}}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/c1/c10b027be63b0c5c1ffc36a76a4a974b.png","alt":null,"title":"","style":[{"key":"width","value":"25%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":"center","origin":null},"content":[{"type":"text","marks":[{"type":"strong","attrs":{}}],"text":"關注「水滴與銀彈」公衆號,7年資深後端研發,和你分享更多優質技術乾貨。","attrs":{}}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章