導語:本文章記錄了本人在學習Python基礎之控制流程篇的重點知識及我的心得,打算入門Python的朋友們能夠來一塊兒學習並交流。
本文重點:python
一、掌握可迭代的對象的定義;
二、掌握可迭代對象、迭代器與生成器之間的關係和異同;
三、熟悉標準庫中生成器。
可迭代的對象
:使用iter內置函數能夠獲取迭代器的對象。若是對象實現了能返回迭代器的__iter__方法,那麼對象就是可迭代的。若是沒有實現__iter__而實現了__getitem__方法,而且其參數是從零開始的索引,這種對象如序列也是可迭代的。向後兼容
:之因此任何Python序列可迭代是爲了向後兼容。ssh
當解釋器須要迭代對象時,會自動調用iter(x):函數
標準的序列都實現了__iter__方法,這是鴨子類型的極端形式。
在白鵝類型中,只要對象實現了__iter__方法,那麼它就是可迭代的對象。學習
注意:
(1)只有實現了__iter__方法的對象能經過子類測試issubclass(Object,abc.Iterator)
(2)檢查對象可否迭代最準確的方法是調用iter(x)函數
,若是不可迭代再處理TypeError。由於iter(x)會考慮到實現__getitem__方法的部分可迭代對象。測試
迭代器:用於從集合中取出元素的對象。
迭代器的功能:用於支持下列操做spa
迭代器的接口協議
:code
迭代器特色:orm
可迭代
。因爲Python中的迭代器實現了__iter__方法,所以也能夠迭代。易耗損
。迭代器通過一次逐次取值的循環後便耗盡了。若想再次迭代須重建迭代器。迭代器檢查方式:調用isinstance(object,abc.Iterator)。
檢查原理:歸結於Iterator.__subclasshook__方法。不管對象所屬的類是Iterator的真實子類仍是虛擬子類,都可以檢查。協程
Python從可迭代的對象中獲取迭代器
。可迭代的對象不是迭代器
。迭代器模式:按需一次獲取一個數據項。
掃描內存中放不下的數據集時,咱們要找到一種惰性獲取數據項的方式,即按需一次獲取一個數據項。這就是迭代器模式(Iterator pattern) 。
迭代器模式的用途:對象
訪問一個聚合對象的內容而無需暴露它的內部表示
;支持對聚合對象的多種遍歷
;爲遍歷不一樣的聚合結構提供一個統一的接口(即支持多態迭代)
。下面構造一個能夠處理文本匹配並迭代的實例:
import reprlib import re reword=re.compile('\w+') #初版:迭代器模式 class Sentence: def __init__(self,text): self.text=text self.words=reword.findall(text) def __repr__(self): return "Sentence({})".format(reprlib.repr(self.text)) def __iter__(self): return SentenceIterator(self.words) class SentenceIterator: def __init__(self,text): self.words=text self.index=0 def __next__(self): try: word=self.words[self.index] except IndexError: raise StopIteration() self.index += 1 return word def __iter__(self): return self title=Sentence('We have a dream!') print(title) for i in title: print(i)
輸出: Sentence('We have a dream!') We have a dream
注意:
(1)不要把迭代器接口應用到可迭代對象上,這是常見的反模式
。
(2)可迭代對象必須實現__iter__方法,但不能實現__next__方法
。
生成器:用於按需生成元素的對象。在Python社區中大多數時候都把迭代器和生成器視做同一律念。
生成器函數:擁有yield關鍵字的Python函數。
生成器表達式:製造生成器的工廠,支持惰性產值。
生成器工廠函數:返回生成器的函數,定義體中能夠沒有yield關鍵字。
生成器函數與生成器表達式優勢比較:
Tips:生成器表達式做爲單參數傳入時無須寫一對括號,而多參數時須將小括號加上。
實例1:經過一個問候同窗的代碼來了解生成器函數是如何工做的
def gen(): print("start") yield "Jack" print("continue") yield "Dennis" print("end") for i in gen(): print("Hello ",i)
輸出: start Hello Jack continue Hello Dennis end
原理分析:不難發現,for循環中操做的對象是生成器中的yield生成的值。緣由在於,生成器是迭代器,會生成傳給yield關鍵字的表達式的值。
注意:無論有沒有return語句,生成器函數都不會拋出StopIteration異常,而是在生成所有值以後直接退出。
實例2:生成器函數改進版
import reprlib import re reword=re.compile('\w+') #第二版:生成器函數 class Sentence: def __init__(self,text): self.text=text self.words=reword.findall(text) def __repr__(self): return "Sentence({})".format(reprlib.repr(self.text)) def __iter__(self): for i in self.words: yield i return title=Sentence('We have a dream!') print(title) for i in title: print(i)
import reprlib import re reword=re.compile('\w+') #第三版:生成器表達式 class Sentence: def __init__(self,text): self.text=text def __repr__(self): return "Sentence({})".format(reprlib.repr(self.text)) def __iter__(self): return (match.group() for match in reword.finditer(self.text)) title=Sentence('We have a dream!') print(title) for i in title: print(i)
Tips:re.finditer函數是re.findall函數的惰性版本,返回的不是列表而是一個生成器,按需惰性生成元素。
過濾
的生成器函數: itertools.takewhile/compress/dropwhile/filter/filterfalse/islice/映射
的生成器函數: 內置的 enumerate/map itertools.accumulate/starmap合併
的生成器函數:itertools.chain/from_iterable/product/zip_longest/ 內置的 zip擴展輸入的可迭代對象
: itertools.combinations/combinations_with_replacement/count/cycle/permutations/repeat產出輸入可迭代對象的所有元素,以某種方式排列
:itertools.groupby/tee/ 內置的 reversed一、歸約函數:接受可迭代對象並返回單個結果的函數。這裏的all和any函數會短路,即一旦得出結果立刻中止迭代。