Pythonノート_反復器、ジェネレータから協程(一)

3884 ワード

最近、古いチュートリアルを見て、最近使用し始めたpython 3と結びつけて、pythonでのコラボレーションの使い方を簡単に紹介しました.本明細書のインスタンスのコードはpython 3.5で実行できます.
以下のチュートリアルでは、以下のチュートリアルがヒントになります.
http://dabeaz.com/coroutines/
1、反復器VS.ジェネレータ(Generator)?
この2つの概念の相関は大きく、簡単に言えば:
  • 反復器が実現しました.next__および_iter__メソッドのオブジェクトです.このオブジェクトは
  • 反復できます.
  • ジェネレータは、関数+yield方式で反復プロトコルを実現する構文であり、関数のように見えますが、普通の関数ではありません.また、ジェネレータは反復だけでなく、コヒーレントな機能も実現します.

  • まず、反復器を手動で定義する例を見てみましょう.
    #        
    from random import randint
    
    class Iter(object):
        def __init__(self,n):
            #                
            self.n = n
            self.i= 0
        
        def __iter__(self):
            return self
    
        def __next__(self):
            if self.i < self.n:
                self.i = self.i+1
                #         100      
                return randint(0,100)
            else:
                #           StopIteration       
                raise StopIteration
    
    if __name__ == '__main__':
        #          
        c=Iter(10)
        for x in c:
        print(x)
        #        
        print('
    ') d=Iter(20) print(d.__next__()) print(d.__next__()) print(d.__next__()) : 44 54 65 22 83 30 86 87 75 46 100 9 1

    同じ反復論理を実装し、ジェネレータのコードの書き方を見てみましょう.
    #       
    from random import randint
    def Gen(n):
        i=0 
        while (i < n): 
            i=i+1
            yield randint(0,100)
    
    if __name__ == '__main__':
        c=Gen(10)
        for x in c:
            print (x)
    

    上記のコードから,同じ論理を実現することは,1つのジェネレータを定義することが反復器を書くよりはるかに簡単であることがわかる.反復器はクラスを書き、ジェネレータは関数を定義します.
    上記の2つの例の反復器のオブジェクトとジェネレータ関数の戻りは異なるが,いずれも同じ機能を実現している.
  • 反復可能なオブジェクト
  • ジェネレータオブジェクト
  • 2、生成器のyield文法糖
    yieldは興味深い構文糖で、1つの関数にyieldがある場合、この関数はもう1つの関数ではなく、ジェネレータオブジェクトを返します.
    2.1ジェネレータの実行順序
    ジェネレータの実行順序:
  • が呼び出されています.next__()またはforループに入ると、関数がyieldに実行されて値が返され、関数が一時停止します.
  • 次回に呼び出す_next__()以降、ジェネレータはyield以降の文の実行を開始します.

  • 例:
    def Gen(n):
        i=0
        while (i>0
    c.__next__()
    >>'step1'
    c.__next__()
    >>'step2'
    c.__next__()
    >>1
    c.__next__()
    >>'step1'
    c.__next__()
    >>'step2'
    c.__next__()
    >>2
    

    2.2ジェネレータオブジェクトのメンバー関数
    2.1の最後の例では、ジェネレータのヘルプドキュメントhelp(c)を表示すると、ジェネレータオブジェクトにはいくつかの重要なメンバー関数が表示されます.
  • __next__()と_iter__():この2つの関数があれば、ジェネレータは反復性
  • を有する.
  • send():この関数は、ジェネレータ関数に新しい値
  • を渡すのに役立ちます.
  • close():このジェネレータを閉じ、閉じた後にジェネレータは
  • を呼び出すことができません.
  • throw():ジェネレータに異常
  • を送信する
    2.2.1 send()
    例:
    #send     
    from random import randint
    
    def Gen(n):
        i=0 
        while (i
        print (c.send('stop'))
    StopIteration
    

    実行結果から見ると、
  • は、最初の2つのnext関数と3番目のsend関数を呼び出し、ジェネレータはyieldで結果を出します.
  • は4回目にsend関数を呼び出した後も反復を開始したが、whileループを終了し、yieldに戻ることはなかったため、最終的な結果には3つの数字
  • しかなかった.
  • は、ジェネレータが閉じているため、next関数を最後に呼び出し、エラーが発生しました.

  • 2.2.2 close()
    例:
    #close     
    from random import randint
    
    def Gen(n):
        i=0 
        while (i
        print (c.__next__())
    StopIteration
    

    close関数の使い方はジェネレータオブジェクトを閉じることですが、sendまたはnext関数を呼び出すと「open」というジェネレータがあり、ジェネレータが閉じるまで実行された中間結果がジェネレータに記録されます.
    2.2.3 throw()
    例:
    #throw     
    from random import randint
    
    def Gen(n):
        i=0 
        while (i

    ジェネレータ内部でこの例外が正常にキャプチャされ、処理され、ジェネレータの後の実行プロセスが遮断されていないことがわかります.