qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          python學習之迭代器

          本節進行迭代器的討論。只討論一個特殊方法---- __iter__  ,這個方法是迭代器規則的基礎。

           

          迭代器規則

          迭代的意思是重復做一些事很多次---就像在循環中做的那樣。__iter__ 方法返回一個迭代器,所謂迭代器就是具有next方法的對象,在調用next方法時,迭代器會返回它的下一個值。如果next方法被調用,但迭代器沒有值可以返回,就會引發一個StopIteration異常。

           

          這里是一個婓波那契數例,使用迭代器如下:

          復制代碼
          class Fibs:     def __init__(self):         self.a = 0         self.b = 1     def next(self):         self.a , self.b = self.b , self.a + self.b         return self.a     def __iter__(self):         return self  >>> fibs = Fibs()  >>> for f in fibs:       if  f  > 1000:           print f           break    #因為設置了break ,所以循環在這里停止。  1597
          復制代碼

          內建函數iter可以從可迭代的對象中獲得迭代器。

          >>> it = iter([1,2,3]) >>> it.next() 1 >>> it.next() 2

           

          從迭代器得到序列

          除了在迭代器和可迭代對象上進行迭代外,還能把它們轉換為序列。在大部分能使用序列的情況下,能使用迭代器替換。

          復制代碼
          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]
          復制代碼

           

           

           

          生成器

           

          生成器也叫 簡單生成器,生成器可以幫助讀者寫出非常優雅的代碼,當然,編寫任何程序時不使用生成器也是可以的。

           

          創建生成器

          創建一個生成器就像創建函數一樣簡單。

          復制代碼
          >>> def flatten(nested):     for sublist in nested:         for element in sublist:             yield element               >>> nested = [[1,2],[3,4],[5]] #使用for循環 >>> for num in flatten(nested):     print num       1 2 3 4 5 #或使用list函數 >>> list(flatten(nested)) [1, 2, 3, 4, 5]
          復制代碼

           

          遞歸生成器

          上面創建的生成器只能處理兩層嵌套,為了處理嵌套使用了兩個for循環,如果要處理任意層的嵌套呢?例如,可以每層嵌套需要增加一個for循環,但不知道有幾層嵌套,所以必須把解決方案變得更靈活,現在可以用遞歸來解決。

          復制代碼
          >>> def fla(aa):     try:         for bb in aa:             for cc in fla(bb):                 yield cc     except TypeError:         yield aa  >>> list(fla([[[1],2],3,4,[5,[6,7]],8]))  #注意括號層次比較多 [1, 2, 3, 4, 5, 6, 7, 8]
          復制代碼

            

          fla被調用時有兩種情況:基本情況和需要遞歸的情況

            在基本的情況中,函數被告知展開一個元素,這種情部下,for循環會引發一個TypeError 異常,生成會產生一個元素。

            如果展開的是一個列表,那么就需要特殊情況處理。程序必須遍歷所有的子列表,并對它們調用fla

          -------------------

          上面的做法有一個問題:如果aa 是一個類似于字符串的對象(字符串、UnicodeUserString等),那么它就是一個序列,不會引發TypeError,但是你不想對這樣的對象進行迭代。

          為了處理這種情況,則必須在生成器的開始處添加一個檢查語句。試著將傳入的對象和一個字符串拼接,看看會不會出現TypeError,這是檢查一個對象是不是類似于字符串最簡單快速的方法。

          復制代碼
          >>> def flatten(nested):     try:        #不要迭代類似字符串的對象         try:nested + ''         except TypeError: pass         else: raise TypeError         for sublist in nested:             for element in flatten(sublist):                 yield element     except TypeError:         yield nested           >>> list(flatten(['foo',['bar',['baz']]])) ['foo', 'bar', 'baz']
          復制代碼

          如果nested+’’ 引發了一個TypError ,它就會被忽略。如果沒有引發TypeError,那么內層try語句就會引發一個它自己的TypeError異常。

           

           

          生成器方法

          生成器新屬性是在開始運行后為生成器提供值的能力。表現為生成器和“外部世界”進行交流的渠道:

            * 外部作用域訪問生成器的send方法,就像訪問next 方法一樣,只不過前者使用一個參數(發送的“消息”---任意對象)

            * 在內部則掛起生成器,yield現在作為表達式而不是語句使用,換句話說,當生成器重新運行的時候,yield方法返回一個值,也就是外部通過send方法發送的值。如果next 方法被使用,那么yield方法返回None. 

          下面簡單的方例子來說明這種機制:

          復制代碼
          >>> def repeater(value):     while True:         new =(yield value)         if new is not None:value = new           >>> r = repeater(42) >>> r.next() 42 >>> r.send("hello, world!") 'hello, world!'
          復制代碼

          生成器的另兩個方法:

            * throw方法(使用異常類型調用,還有可選的值以及回溯對象)用于在生成器內引發一個異常(在yield表達式中)

            * close 方法(調用時不用參數)用于停止生成器。

          posted on 2014-02-17 15:18 順其自然EVO 閱讀(171) 評論(0)  編輯  收藏 所屬分類: python

          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 伊通| 综艺| 县级市| 富裕县| 武清区| 岳池县| 穆棱市| 扎囊县| 奉贤区| 石阡县| 景东| 维西| 班玛县| 乌审旗| 太原市| 凌海市| 定兴县| 米泉市| 昭通市| 荣昌县| 东辽县| 南华县| 淅川县| 康保县| 南阳市| 紫云| 宁德市| 保山市| 鄂温| 措美县| 丰宁| 石景山区| 伊川县| 庆城县| 开鲁县| 天镇县| 南宫市| 涞水县| 台南县| 大姚县| 南川市|