一. 迭代器python
在前面的筆記中,已經提到過迭代器(和可迭代),這裏會對此進行深刻討論。只討論一個特殊方法---__iter__,這個方法是迭代器規則的基礎。函數
1.1 迭代器規則spa
迭代的意思是重複作一些事情不少次,到如今爲止只是在for循環中對序列和字典進行迭代,但實際上也能對其餘的對象進行迭代:實現__iter__方法的對象。code
__iter__方法返回一個迭代器,所謂迭代器就是具備next方法(這個方法在調用時不須要任何參數)的對象。在調用next方法時,迭代器會返回它的下一個值。若是next方法被調用,但迭代器沒有值能夠返回,就會引起一個StopIteration異常。對象
爲何不用列表?列表是一次性獲取全部值的,若是有不少值,列表會佔用太多的內存,可是迭代器能夠在使用時計算一個值時獲取一個值,使用迭代器更通用,簡單,優雅。blog
下面來看一個不使用列表的例子:教程
__metaclass__ = type class Fibs: def __init__(self): self.a = 0 self.b = 0 def next(self): self.a,self.b = self.b,self.a + self.b return self.a def __iter__(self): return self
注意:迭代器實現了__iter__方法,這個方法實際上返回迭代器自己。不少狀況下,__iter__會放到其餘的會在for循環中使用的對象中。這樣一來,程序就能返回所需的迭代器。此外,推薦使用迭代器實現它本身的_iter__方法,而後就能直接在for循環中使用迭代其自己了。遞歸
>>> f = Fibs() >>> for n in f: if n > 10: print n break 13
1.2 從迭代器獲得序列內存
除了在迭代器和可迭代對象上進行迭代外,還能把它們轉換爲序列。在大部分能使用序列的狀況下,能使用迭代器替換。關於這個的一個頗有用的例子是使用list構造方法顯式地將迭代器轉化爲列表。element
__metaclass__ = type class TestIterator: value = 0 def next(self): self.value += 1 if self.value > 10:raise StopIteration return self.value def __iter__(self): return self
>>> ti = TestIterator() >>> list(ti) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
二. 生成器
生成器是python新引入的概念,因爲歷史緣由,它也叫簡單生成器。它和迭代器多是近幾年來引入的最強大的兩個特性。生成器能夠幫助讀者寫出很是優雅的代碼。
生成器是一種用普通的函數語法定義的迭代器。讓咱們先看看怎麼建立和使用生成器,而後再瞭解一下她的內部機制。
2.1 建立生成器
首先建立一個展開嵌套列表的函數,參數是一個列表的列表,相似於nested = [[1,2],[3,4],[5]],函數按照順序打印出列表中的數字:
__metaclass__ = type def flatten(nested): for sublist in nested: for element in sublist: yield element
這個函數首先迭代提供的嵌套列表中的全部子列表,而後按順序迭代列表中的元素。yield語句是新知識,任何包含yield語句的函數都稱爲生成器。它不像return那樣返回值,而是每次產生多個值。每次產生一個值,函數就會被凍結:即函數停在那點等待被激活,函數被激活後就從中止的那點開始執行。
接下來能夠經過在生成器上迭代來使用全部的值:
>>> nested = [[1,2],[3,4],[5]] >>> for num in flatten(nested): print num 1 2 3 4 5
2.2 遞歸生成器
上面的例子中只能處理兩層嵌套,若是不知道有多少層嵌套呢?咱們就要求助於遞歸了:
__metaclass__ = type def flatten(nested): try: for sublist in nested: for element in sublist: yield element except TypeError: yield nested
當flatten被調用時,有兩種可能性:基本狀況和須要遞歸的狀況,在特殊狀況中,展開的是一個列表,程序必須遍歷全部的字列表,並對他們調用flatten。而後用另外一個for循環來產生被展開的子列表中的全部元素。
>>> nested = [[1,2],[3,4],[5,[6,[7]]]]
>>> for num in flatten(nested):
print num
1
2
3
4
5
[6, [7]]
(上面的結果跟書《python基礎教程(第二版)》中例子的結果不同,我也搞不懂)