ホームページ  >  記事  >  バックエンド開発  >  歩留まりについての深い理解

歩留まりについての深い理解

高洛峰
高洛峰オリジナル
2016-10-18 09:05:421107ブラウズ

英語の 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 を含む関数

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

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

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

2. Yield は式です

Python 2.5 より前では、yield はステートメントでしたが、Python 2.5 では、yield は次のような式 (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を含む関数を実行するかを理解した後、次を見てみましょう。もう 1 つは非常に重要な関数 send(msg) です。実際、 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) してください。 ) の場合、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() でジェネレーターを中断します

ジェネレーターの中断は非常に柔軟な手法であり、スローすることができます。 through throw 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) を呼び出すと、例外がスローされます。

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