python學習筆記之八:迭代器和生成器

一. 迭代器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基礎教程(第二版)》中例子的結果不同,我也搞不懂)

相關文章
相關標籤/搜索