pythonのyieldキーワード

3934 ワード


反復可能オブジェクトmylistは反復可能なオブジェクトです.リスト生成式を使用してリストを作成すると、反復可能なオブジェクトが作成されます.
mylist = [x*x for x in range(3)]
    for i in mylist :
       print(i)
0
1
4

ここでは、すべての値がメモリに存在するため、大量のデータには適していません.
ビルダー
  • 反復可能
  • は、
  • を1回しか読み取ることができない.
  • リアルタイムでデータを生成し、メモリに
  • が不完全に存在する.
    yieldキーワード
  • yieldreturnのようなキーワードですが、この関数はジェネレータ
  • を返します.
  • この関数を呼び出すと、関数内部のコードはすぐに実行されず、この関数はジェネレータオブジェクト
  • を返すだけです.
  • forを使用して反復すると、関数のコードは
  • を実行します.
     def createGenerator() :
        mylist = range(3)
           for i in mylist :
               yield i*i
    
    >>> mygenerator = createGenerator() # create a generator
    >>> print(mygenerator) # mygenerator is an object!
    
        
        for i in mygenerator:
            print(i)
    0
    1
    4

    最初の反復では関数が実行され、最初からyieldキーワードに到達し、yield後の値を最初の反復の戻り値として返します.その後、この関数を実行するたびに、関数内で定義したループの次のループを実行し続け、戻ることができないまでその値を返します.
    反復器、次にジェネレータを理解し、最後にyeildの機能を見て、yieldに遭遇すると戻りますが、ジェネレータを返します.mygenerator = createGenerator() # create a generator .
    また、ネット上では、説明も悪くない文章を見ました.https://blog.csdn.net/mieleizhi0522/article/details/82142856?utm_source=blogxgwz0
    もしあなたがまだyieldに対して初歩的な認識を持っていないならば、あなたはまずyieldを“return”と見なして、これは直観的で、それはまずreturnで、普通のreturnはどういう意味で、プログラムの中である値を返して、帰ってからプログラムはもう下へ実行しません.returnを見てからジェネレータ(generator)の一部(yield付きの関数こそ本当の反復器)と見なします.よし、これらが分からない場合は、yieldをreturnと見なして、次のプログラムを直接見ると、yieldのすべての意味がわかります.
    def foo():
        print("starting...")
        while True:
            res = yield 4
            print("res:",res)
    g = foo()
    print(next(g))
    print("*"*20)
    print(next(g))
    

    しゅつりょく
    starting...
    4
    ********************
    res: None
    4
    

    コードの実行順序を直接説明します.コードの単一ステップデバッグに相当します.
    1.プログラムが実行を開始すると、foo関数にyieldキーワードがあるため、foo関数は実際に実行されるのではなく、まずジェネレータg(オブジェクトに相当)が得られる
    2.nextメソッドが呼び出されるまでfoo関数は正式に実行を開始し、foo関数のprintメソッドを実行してからwhileループに入ります.
    3.プログラムはyieldキーワードに出会って、それからyieldをreturnと考えて、returnは1つの4の後で、プログラムは停止して、res操作に値を割り当てることを実行していないで、この時next(g)文の実行は完成して、だから出力する前の2行(1つ目はwhileの上のprintの結果で、2つ目はreturnの出た結果)はprint(next(g))を実行する結果で、
    4.プログラム実行print(「*」*20)、出力20個*
    5.また次のprint(next(g))を実行し始めます.このときは上とあまり差がありませんが、このときはさっきのnextプログラムが停止したところから実行されます.つまりresの付与操作を実行するので、注意してください.このとき賦値操作の右側には値がない(さっきはreturnが出ていたので、賦値操作の左にパラメータが渡されていない)ので、このときres賦値はNoneなので、次の出力はres:Noneです.
    6.プログラムはwhileで実行され続け、yieldに再び遭遇します.このときもreturnが4を出し、プログラムが停止します.print関数が出力する4が今回のreturnが4を出ます. 
    def foo():
        print("starting...")
        while True:
            res = yield 4
            print("res:",res)
    g = foo()
    print(next(g))
    print("*"*20)
    print(g.send(7))
    

    このジェネレータのsend関数の例を見て、この例は上の例の最後の行を交換して、結果を出力します.
    starting...
    4
    ********************
    res: 7
    4
    

    まずsend関数の概念を大まかに説明します:この時あなたは上のあの紫色の字に気づくべきで、それから上のあのresの値はどうしてNoneで、これは7になって、いったいどうして、これはsendが1つのパラメータをresに送ったので、上で述べたように、returnの時、4をresに与えていないので、次回実行する時は賦値操作を続けるしかありません.仕方なくNoneとして付与し、sendを使用すると、実行を開始するときは、前回(return 4以降)に続いて実行し、まず7をresに付与し、nextの役割を実行し、次回のyieldに出会ってreturnが結果を出して終了する.
    5.プログラムはg.send(7)を実行し、yieldキーワードの行から下へ実行し続け、sendは7という値をres変数に付与する
    6.sendメソッドにnext()メソッドが含まれているため、プログラムはprintメソッドを実行し続け、whileループに再び進みます.
    7.プログラム実行は再びyieldキーワードに遭遇し、yieldは後の値を返した後、nextメソッドまたはsendメソッドが再び呼び出されるまでプログラムは再び一時停止する.
     
    なぜこのジェネレータを使うのかというと、Listを使うと、0,1,2,3,4,5,6を取るなど、より大きなスペースを占めるからです.1000
    あなたはそうするかもしれません.
    for n in range(1000):
        a=n
    

    このときrange(1000)はデフォルトで1000個の数を含むlistを生成するので、メモリを占めています.
    このとき先ほどのyieldをジェネレータに組み合わせて実装したり、xrange(1000)というジェネレータで実装したりすることができます
    yieldの組み合わせ:
    def foo(num):
        print("starting...")
        while num<10:
            num=num+1
            yield num
    for n in foo(0):
        print(n)
    

    出力:
    starting...
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10