python学習ノートのyield



Pythonプログラミング言語は比較的新しいプログラムアプリケーション言語として、開発者が徐々に熟練しなければならない方法がたくさんあります.例えば今日ご紹介するPython yieldは、比較的特殊なアプリケーションです.yieldの英语の単语の意味は生产で、Pythonに触れたばかりの时とても困惑して、ずっとPython yieldの使い方を理解していません.ただ、yieldは、次の例のような関数に値プラグデータを返すために使用できることをざっと知っています.

  
  
  
  
  1. def addlist(alist):  
  2. for i in alist:  
  3. yield i + 1 

alistの各項目を取り出し、i+1を詰めます.各アイテムを呼び出して取り出します.

  
  
  
  
  1. alist = [1, 2, 3, 4]  
  2. for x in addlist(alist):  
  3. print x, 

これは確かにPython yieldアプリケーションの一例ですが、limodouの文章「2.5版yieldの学習心得」を見て、自分で繰り返し体験した後、yieldに対して新しい理解を得ました.
1.yieldを含む関数
ある関数にyieldが含まれているのを見たら、この関数はすでにGeneratorであり、その実行は他の一般的な関数とは多くの違いがあることを意味します.たとえば、次の簡単な関数です.

  
  
  
  
  1. def h():  
  2. print 'To be brave'  
  3. yield 5  
  4. h() 

h()を呼び出した後、print文は実行されなかったことがわかります.これがyieldです.では、print文を実行するにはどうすればいいのでしょうか.これが後で議論する問題で、後の議論と学習を通じてyieldの動作原理がわかります.
 
2.yieldは式です
Python2.5以前はPython yieldは文でしたが、2.5ではyieldはエクスプレッション(Expression)です.たとえば、次のようになります.

  
  
  
  
  1. m = yield 5 

式(yield 5)の戻り値はmに与えられるので,m=5は誤りであると考えられる.では、(yield 5)の戻り値をどのように取得しますか?後述するsend(msg)メソッドを使用する必要があります.
3.next()文を通して原理を見る
では、yieldの動作原理を説明します.yield式があるため、上のh()が呼び出されても実行されないことを知っています.そのため、next()文で実行させます.next()文は、次のyield式までGenerator実行を復元します.例:

  
  
  
  
  1. def h():  
  2. print 'Wen Chuan'  
  3. yield 5  
  4. print 'Fighting!'  
  5. c = h()  
  6. c.next()c.next() 

呼び出し後、h()はyield 5に遭遇するまで実行を開始するので、結果を出力する.

  
  
  
  
  1. Wen Chuan 

c.next()を再び呼び出すと、次のyield式が見つかるまで実行が続行されます.後ろにPython yieldがないため、異常が放出されます.

  
  
  
  
  1. Wen Chuan  
  2. Fighting!  
  3. Traceback (most recent call last):  
  4. File "/home/evergreen/Codes/yidld.py", line 11, in <module> 
  5. c.next()  
  6. StopIteration 

4.send(msg)とnext()
next()がyieldを含む関数をどのように実行するかを理解した後,もう一つの非常に重要な関数send(msg)を見てみよう.実はnext()とsend()は一定の意味で類似しており、send()はyield式の値を伝達することができ、next()は特定の値を伝達することができず、Noneを伝達するしかないという違いがある.したがって,c.next()とc.send(None)の役割は同じであると見なすことができる.この例を見てみましょう.

  
  
  
  
  1. def h():  
  2. print 'Wen Chuan',  
  3. m = yield 5 # Fighting!  
  4. print m  
  5. d = yield 12  
  6. print 'We are together!'  
  7. c = h()  
  8. c.next() # c.send(None)  
  9. c.send('Fighting!') #(yield 5) 'Fighting!' :  
  10. Wen Chuan Fighting! 

注意しなければならないのは、最初に呼び出すときはnext()文またはsend(None)を使用して、sendを使用してNone以外の値を送信することはできません.そうしないと、Python yield文がこの値を受信しないため、エラーが発生します.
5.send(msg)とnext()の戻り値
send(msg)とnext()には戻り値があり、それらの戻り値は特殊で、次のyield式のパラメータを返します.例えばyield 5は、5を返します.ここまで来て、何か分かったのではないでしょうか.本明細書の第1の例では、for i in alistによってGeneratorを巡回するが、実際には毎回alistが呼び出される.毎回alist.Next()の戻り値はyieldのパラメータであり,すなわち我々は押し込まれたものと考え始めた.上記の例を続けます.

  
  
  
  
  1. def h():  
  2. print 'Wen Chuan',  
  3. m = yield 5 # Fighting!  
  4. print m  
  5. d = yield 12  
  6. print 'We are together!'  
  7. c = h()  
  8. m = c.next() #m  yield 5   5  
  9. d = c.send('Fighting!') #d  yield 12  12  
  10. print 'We will never forget the date', m, '.', d :  
  11. Wen Chuan Fighting!  
  12. We will never forget the date 5 . 12