収量の詳細な紹介

巴扎黑
巴扎黑オリジナル
2017-09-04 11:36:381749ブラウズ

英語の yield は生産を意味します。初めて Python に触れたとき、私は非常に混乱し、yield の使い方がわかりませんでした。

私は、次の例のように、 yield を使用して関数の戻り値にデータを詰め込むことができることを大まかに知っています:

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

alist の各項目を取り出し、それに i + 1 を詰め込みます。次に、呼び出して各項目を取り出します:

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

これはまさに yield アプリケーションの例です

1. yield を含む関数が表示されている場合、この関数はすでにジェネレーターであることを意味します。他の通常の関数とは大きく異なります。たとえば、次の単純な関数:

def h():
    print 'To be brave'
    yield 5
h()

h() を呼び出した後、print ステートメントが実行されていないことがわかります。これは yield ですが、print ステートメントを実行するにはどうすればよいでしょうか?これについては後で説明します。この後の議論と検討を通じて、収量がどのように機能するかが理解できるようになります。

2. Yield は式です

Python 2.5 より前では、yield はステートメントでしたが、Python 2.5 では、次のような式 (Expression) になりました。

m = yield 5

expression (yield 5 )は m に代入されるため、m = 5 と考えるのは間違いです。では、戻り値 (yield 5) を取得するにはどうすればよいでしょうか?後で紹介する send(msg) メソッドを使用する必要があります。

3. next() ステートメントを通して原理を確認してください

それでは、収量の動作原理を明らかにしましょう。上記の h() は、yield 式を持っているため、呼び出された後に実行されなかったことがわかっているため、next() ステートメントを通じて実行させます。 next() ステートメントは、次の yield 式までジェネレーターの実行を再開します。例:

def h():
    print 'Wen Chuan'
    yield 5
    print 'Fighting!'
c = h()
c.next()

c.next() が呼び出された後、h() は yield 5 に到達するまで実行を開始します。そのため、出力結果は次のようになります:

Wen Chuan

c.next() を再度呼び出すと、実行は次のようになります。次の yield 式が見つかるまで続行します。その後に yield がないため、例外がスローされます:

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

4. send(msg) と next()

next() がどのように yield を含む関数を実行するかを理解した後、別の非常に重要な関数を見てみましょう。送信(メッセージ)。実際、 next() と send() は、ある意味では同様の関数を持っています。違いは、send() は yield 式の値を渡すことができるのに対し、next() は特定の値を渡すことができず、None のみを渡すことができるということです。したがって、

c.next() と c.send(None) は同じ効果があることがわかります。

この例を見てください:

def h():
    print &#39;Wen Chuan&#39;,
    m = yield 5  # Fighting!
    print m
    d = yield 12
    print &#39;We are together!&#39;
c = h()
c.next()  #相当于c.send(None)
c.send(&#39;Fighting!&#39;)  #(yield 5)表达式被赋予了&#39;Fighting!&#39;

出力結果は次のとおりです:

Wen Chuan Fighting!

初めて呼び出すときは、next() ステートメントまたは send(None) を使用してください。 use send None 以外の値を送信します。送信しないと、この値を受け取る yield ステートメントがないため、エラーが発生します。

5. send(msg) と next() の戻り値

send(msg) と next() の戻り値は、次の yield 式のパラメーターを返します。たとえば、yield 5 の場合、5 が返されます。ここで何か理解できましたか?この記事の最初の例では、alist の for i を介してジェネレーターをトラバースすることにより、alist.Next() が実際に毎回呼び出され、毎回の alist.Next() の戻り値が yield のパラメーターになります。何かが押し込まれているのではないかと思い始めます。上記の例を続けてみましょう:

def h():
    print &#39;Wen Chuan&#39;,
    m = yield 5  # Fighting!
    print m
    d = yield 12
    print &#39;We are together!&#39;
c = h()
m = c.next()  #m 获取了yield 5 的参数值 5
d = c.send(&#39;Fighting!&#39;)  #d 获取了yield 12 的参数值12
print &#39;We will never forget the date&#39;, m, &#39;.&#39;, d

出力結果:

Wen Chuan Fighting!
We will never forget the date 5 . 12

6. throw() と close() ジェネレーターの中断

ジェネレーターの中断は、GeneratorExit 例外をスローすることでジェネレーターを終了することができます。実際、Close() メソッドには同じ機能があり、内部で throw(GeneratorExit) を呼び出します。見てみましょう:

def close(self):
    try:
        self.throw(GeneratorExit)
    except (GeneratorExit, StopIteration):
        pass
    else:
        raise RuntimeError("generator ignored GeneratorExit")
# Other exceptions are not caught

したがって、close() メソッドを呼び出してから next() または send(msg) を呼び出すと、例外がスローされます:

Traceback (most recent call last):
  File "/home/evergreen/Codes/yidld.py", line 14, in <module>
    d = c.send(&#39;Fighting!&#39;)  #d 获取了yield 12 的参数值12
StopIteration

以上が収量の詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。