說說Python中的iterator,yield運算式及generator,coroutine,iteratorcoroutine

來源:互聯網
上載者:User

說說Python中的iterator,yield運算式及generator,coroutine,iteratorcoroutine

每次去看別人寫的代碼都有個yield,感覺超級geek,今天花點兒時間整理下。

按照順序來:

1. iterator

    iterator叫做迭代器,用來遍曆可以序列化的資料,比如一個list,set 等,當然如果對象想要能夠使用迭代器來遍曆,只要在該對象的類中添加__iter__()方法,該方法返回一個迭代器對象,迭代器對象中需要實現next()方法,例子如下:

>>> class sequenceClass(object):...     def __init__(self, *args):...             self._data = list(args)...     def __iter__(self):...             return DataIter(self)...>>> class DataIter(object):...     def __init__(self, data):...             self._index = 0...             self._data = data._data...     def next(self):...             if self._index >= len(self._data): raise StopIteration()...             d = self._data[self._index]...             self._index += 1...             return d... >>> data = sequenceClass(1,2,3,4)>>> for x in data: print x... 1234
執行方法如下:

    建立對象data :   data = sequenceClass(1,2,3,4)
    使用for迴圈遍曆data:

        1.第一次for迴圈遍曆data時,調用了data的__iter__()方法,該方法返回一個迭代器對象:DataIter

        2.接著for迴圈每次調用DataIter對象的next()方法,next()方法返回資料

  3.等到資料遍曆完成時,拋出異常StopIteration, 該異常被for迴圈撲獲,遍曆結束。

以上是iterator的實現方法,但有一種更加簡單的方式,但初學時可能不太好理解,就是使用yield運算式來遍曆對象。


2.yield運算式及genetator

     Python中,凡是含有yield的函數,被調用時都返回一個generator對象。generator設計的目的是能夠更加簡單的實現迭代器協議,例如上面的例子,需要單獨寫一個類來遍曆資料,而用generator,直接一個yield運算式就可以用做迭代器了。

看一個例子:

>>> def test_generator():...     s = 0...     for i in xrange(10):...             s = yield i * s...             print 'i:', i...             print 's:', s...             print 'i * s', i * s... >>> t = test_generator()>>> t<generator object test_generator at 0x10403a820>>>> >>> t.next()0>>> t.send(10)i: 0s: 10i * s 010>>> t.send(11)i: 1s: 11i * s 1122

一步步講解:

    1.定義了一個函數叫做test_generator

    2.調用test_generator,得到t對象

    3.運行t時,是一個generator對象

    4.t.next()或者t.send(None)啟動generator對象, generator對象運行到yield,將yield右面的運算式的值返回,並儲存generator對象當前的狀,因此,後面的列印都沒有被執行。

    5.t.send(10)

         1)將輸入的值10賦值給s

         2)執行yield後面的運算式,即將所有print執行完畢,解析如下:

               由於在第4步generator儲存了對象的當前的狀態,因此: i = 0, s是剛輸入的值為10, i *s 當然就為0了,接著進入下一次迴圈,此時i= 1,執行yield運算式,結果得10,儲存當前generator狀態,返回10,generator停止運行。

   6.t.send(11)

        1)和第5步類似了,將11輸入給s

        2)因為第5步,generator儲存了當前的對象的值,因此: i = 1, s是剛輸入的值為11, i *s 當然就為11了,接著進入下一次迴圈,此時i= 2,執行yield運算式,結果得22,儲存當前generator狀態,返回22,generator停止運行。

   7.接下來在調用t.send(num),和第5,6步一樣,直到generator內部的迴圈完成,當再次調用時,將拋出異常:StopIteration


總結一下:

     1. yield運算式, 四種形式:

           a. 不接受輸入值或者輸入值是None

                   yield 1

           b. 接受輸入值

                   s = yield 1

           c. 接受輸入,但不返回資料,這樣預設返回None

                   s = yield

           d.既不接受輸入,也不返回值,預設返回None

                   yield

           第一種:當函數調用到yield時,返回yield的右邊經過計算的值 ,這裡說計算的意思是,yield後面可以寫成函數,運算式等,

           第二種:當函數調用到yield時,必須傳入一個值,該值存入s中,然後返回yield後面的運算式的值並儲存目前狀態

           第三種:只是將資料接受進來,然後執行yield後的語句,再次執行到yield時,儲存目前狀態並返回,這樣的用例一般是

                         只列印一些處理訊息,而不需要結果的方式。

           第四種:這樣的只能遍曆generator內部的資料了。

2.使用generator的好處:

      1)可以很方便的實現迭代器,即yield不接受輸入值

       2)使用generator可以減少記憶體的使用,因為遍曆出來的值都是每次進行計算的,不用一次性全部計算完成,然後一個個

     遍曆,最終釋放掉;另外可以在yield後面做一些操作,可以很隨意的控制返回值。


3.coroutine 協程

      使用yield的函數,若用send來控制,就算coroutine了,若用for迴圈來控制,就算generator或者iterator,使用方法大多見於

decorator, 如tornado中的gen.coroutine。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.