国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

詳解Python3中的迭代器和生成器及其區別

2020-01-04 14:24:18
字體:
來源:轉載
供稿:網友

介紹

本篇將介紹Python3中的迭代器與生成器,描述可迭代與迭代器關系,并實現自定義類的迭代器模式。

迭代的概念

上一次輸出的結果為下一次輸入的初始值,重復的過程稱為迭代,每次重復即一次迭代,并且每次迭代的結果是下一次迭代的初始值

注:循環不是迭代

while True: #只滿足重復,因而不是迭代print('====>')

 迭代器

1.為什么要有迭代器?

對于沒有索引的數據類型,必須提供一種不依賴索引的迭代方式。

2.迭代器定義:

迭代器:可迭代對象執行__iter__方法,得到的結果就是迭代器,迭代器對象有__next__方法

它是一個帶狀態的對象,他能在你調用next()方法的時候返回容器中的下一個值,任何實現了__iter__和__next__()方法的對象都是迭代器,__iter__返回迭代器自身,__next__返回容器中的下一個值,如果容器中沒有更多元素了,則拋出StopIteration異常

可迭代的(iterable)

Python標準庫中存在著一些可迭代對象,例如:list, tuple, dict, set, str等。

可以對這些迭代對象,進行for-in等迭代操作,例如:

for s in "helloworld":  print(s)

編譯器若想迭代一個對象a,則會自動調用iter(a)獲取該對象的迭代器(iterator),如果iter(a)拋出異常,則對象a不可迭代。

判斷對象是否可迭代

原生函數iter(instance) 可以判斷某個對象是否可迭代,它的工作流程大概分為以下3個步驟:

  • 檢查對象instance是否實現了__iter__方法,并調用它獲取返回的迭代器(iterator)。
  • 如果對象沒有實現__iter__方法,但是實現了__getitem__方法,Python會生成一個迭代器。
  • 如果上述都失敗,則編譯器則拋出TypeError錯誤,‘xxx' Object is not iterable。

自定義類實現__iter__方法

根據第一條,我們自定義類Iter1實現__iter__方法使該類的對象可迭代。

class Iter1:  def __init__(self, text):    self.text = text  def __iter__(self):    return iter(self.text)iter1 = Iter1("hello")for s in iter1:  print(s)

Iter1類實現了__iter__方法,通過iter()調用,得到可迭代對象text的迭代器并返回,實現了迭代器協議,因此可以通過for-in等方式對該對象進行迭代。

第二條通常都是針對Python中的序列(sequence)而定義,例如list,為了實現sequence協議,需要實現__getitem__方法。

class Iter2:  def __init__(self, sequence):    self.sequence = sequence  def __getitem__(self, item):    return self.sequence[item]iter2 = Iter2([1, 2, 3, 4])for s in iter2:  print(s)

實際上,為了避免版本后序改動,Python標準庫中的序列除了實現了__getitem__方法,也實現了__iter__方法,因此我們在定義序列時也應實現__iter__。

綜上,如果顯示判斷某個對象是否可迭代,應該調用iter(instance)是否拋出異常,因為只實現了__getitem__的序列也是可迭代的(例子中Iter2的對象是可迭代的,但isinstance(iter2, abc.Iterator)返回結果是False)。同時,如果在調用iter后進行迭代操作不必顯示判斷,可以用try/except方式包裝代碼塊。

iterable vs iterator(可迭代vs迭代器)

iterable定義

任何可以由原生函數iter獲取到迭代器的對象
任何實現了__iter__方法并返回迭代器的對象
所有的序列(實現了__getitem__)

Python通過獲取到可迭代對象的迭代器(iterator)實現迭代,例如for-in的實現其實是在內部獲取到了迭代器進行操作。for-in機制可以理解為下述代碼:

s = 'hello'it = iter(s)while (True):  try:    print(next(it))  except StopIteration:    del it    break

StopIteration異常將在迭代器耗盡后被拋出,for-in、生成式(comprehension)、元組解壓(tuple unpacking)等迭代操作都會處理并這個異常。

迭代器是個迭代值生產工廠,它保存迭代狀態,并通過next()函數產生下一個迭代值。實現迭代器需要實現以下兩個方法:

__iter__ 
返回self

__next__
返回下一個可用的元素,如果無可用元素則拋出StopIteration異常

迭代器實現__iter__,因此所有的迭代器都是可迭代的,下圖展示了iterable和iterator的結構。

Python3,迭代器,生成器

迭代器模式

實現一個自定義的迭代器模式需要兩個類,分別為實現了__iter__方法的類和通過__iter__返回的迭代器實例類(實現了__iter__和__next__方法)。下面例子簡單實現了上述功能。

class IterText:  def __init__(self, text):    self.text = text  def __iter__(self):    return IteratorText(self.text)class IteratorText:  def __init__(self, text):    self.text = text    self.index = 0  def __iter__(self):    return self  def __next__(self):    try:      letter = self.text[self.index]    except IndexError:      raise StopIteration    self.index += 1    return lettertext = IterText("hey")for l in text:  print(l)

可迭代的IterText實現了__iter__方法,返回了迭代器IteratorText實例。IteratorText實現了__next__方法返回下一個迭代元素直到拋出異常,同時IteratorText實現了__iter__方法返回自身對象用于迭代。
這里的IterText和IteratorText很容易混淆,如果在IterText中實現了__next__方法并將__iter__中返回自身實例self也可以實現上述功能,但通??傻鷮ο蠛偷鲬敺珠_,這樣在可迭代對象中的__iter__中可以返回不同的迭代器對象,使功能獨立。

生成器(generator)

通過上述文章說明,迭代器通過next()不斷產出下一個元素直到迭代器耗盡,而Python中的生成器可以理解為一個更優雅的迭代器(不需要實現__iter__和__next__方法),實現了迭代器協議,它也可以通過next()產出元素。
Python中的生成器主要分為兩種類型:

生成器函數(generator function)返回得到的生成器:

包含yield關鍵字的函數稱為生成器函數

def gen_func():  yield 1  yield 2  yield 3g = gen_func()

生成器表達式(generator expression)返回得到的生成器

g = (i for i in (1, 2, 3))

我們可以利用生成器進行迭代操作:

for e in g:  print(e)  ## 生成器g已被耗盡,如果需要重新迭代需要重新獲得新的生成器對象g = gen_func()for e in g:  print(e)

利用生成器代替可迭代中的__iter__迭代器

在迭代器模式章節中,我們在可迭代IterText中的__iter__返回迭代器IteratorText實例,然而使用生成器的方式會使代碼更加優雅。

class IterText:  def __init__(self, text):    self.text = text  def __iter__(self):    for letter in self.text:      yield letter

因為yield存在于__iter__,因此__iter__變成了生成器函數,調用它測返回一個生成器,同時生成器又實現了迭代器協議,因此IterText滿足了可迭代的需求。

總結

本篇介紹了Python中的可迭代(iterable)、迭代器(iterator)以及它們的關系,并講述了迭代器模式的實現,同時通過Python中的生成器完善了迭代器模式。希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到python教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 双辽市| 富民县| 浦江县| 渭源县| 儋州市| 巴林左旗| 昌黎县| 革吉县| 西青区| 芜湖市| 西宁市| 万州区| 大兴区| 澄城县| 会宁县| 寻甸| 原阳县| 军事| 长治市| 石阡县| 德庆县| 土默特左旗| 蕲春县| 兴海县| 综艺| 阜新市| 金溪县| 湖口县| 竹山县| 宿松县| 北宁市| 逊克县| 同江市| 榆树市| 紫金县| 呼伦贝尔市| 克东县| 喀喇沁旗| 陆丰市| 博兴县| 鹤壁市|