python の yield。サクッと理解するには return と比較

yield がどうもピンとこない

python の yield は非常に便利ですが、イマイチ判りにくかったりします。内部的な仕組み、たとえば iter とか next を理解しとけばいいのですが、それはそれで面倒です。

そこで内部の仕組みはひとまず横において、とりあえず yield の動きを理解することを目指します。そして、そういう目的なら return と比較するのが簡単です。

- 目次 -

スポンサーリンク

return との比較

returnyeild を比較してみます。

まず return ですが、戻り値のある return の動作は

  • 関数の処理を 終了
  • 値を返す

です。

一方、yeild

  • 関数の処理を 一旦停止
  • 値を返す

という動きをします。
一旦停止なので、yeild の処理は再開されます。

図にすると

ret_func
ret_func

yeild の場所で一旦停止し、再開時は次の行からスタートします(再開のきっかけは後述)。

なんのために ?

でわ、yield があると何が便利なのでしょうか。

単純な例ですが、たとえば 1GB の巨大なテキストファイルがあるとします。そして、この巨大なファイルを読み込み、データを渡してくれる関数を作るとします。

これを普通にやろうとすると、受け渡し用のメモリが 1GB という巨大なサイズになってしまいます。

ところが yield を使えば、少量、たとえば 1 行づつデータを読み込み、その都度 yield すればいいので、メモリの使用量はほんの僅かで済んでしまいます。

yield return

使ってみる

ループで

yield がなくなるまで for 文が回りつづけます。
for 文の裏側で 「処理(yield まで) ⇒ 一旦停止 ⇒ 再開(yield まで) ⇒ 一旦停止」 が繰り返され、その都度、yield の返す値が x に代入されます。

ループ以外で

for 文のような繰り返し処理を使わない場合は、内部の仕組みを自分で意識する必要があります。

yield を含む関数を呼び出すと generator(ジェネレータ)というものが返ってきます。そのジェネレータの next() を呼ぶと、yield までの処理を実行し、値を返してくれます。next() をもう一度呼ぶと、yield の次の行から再開され、次の yield まで処理を実行し、値を返してくれます。
yield の個数以上に next() を呼ぶと StopIteration 例外が raise されます。

スポンサーリンク
その他の記事
  1. python嫌いおじさん says:

    パーフェクトPythonという本をパラパラ立ち読みしててyeildが出てきて、説明が雑だったので見に来ました! 図や簡単なコードで説明されてて、とてもわかりやすいです! 感謝…

    • python嫌いおじさん、こんにちわ。

      コメント、どうもありがとうございます。
      python嫌いなどと言わず、ぜひ Anaconda あたりから。

  2. わかりやすい記事をありがとうございます。初心者ですがreturnとyeildの違いがなんとなく理解できました。

  3. なるほど!yieldは「いったん停止して戻る」動きなんですね。わかりやすい解説をありがとうございました。

  4. Scrapyがんばっぞ! says:

    Scrapyをやりながら、yieldで色々と迷っていました!
    こちらの解説でようやく腑に落ちました。
    ありがとうございます。

  5. ジェネレーターに関して調べていて、ここに行き着きました。
    とても分かりやすかったです。
    参考にさせていただきました。
    外部リンクで紹介させていただきます。

  6. やっとyieldの意味が分かりました
    こうして徹底的に「何を意図して使うか」の観点にしてもらうと、入門書の四角い文章よりもスッと概念が頭に入ってくるので助かります、ありがとうございました

  7. わかりやすい解説、ありがとうございます。一つコメントです。yieldを含む関数がgenerator関数で、generatorの返り値は(generator) iterater オブジェクトでは?

  8. 通りすがり says:

    いやいや、ループでyieldを使う例が、分かりにくいでしょう。
    yield使うだけで、何の調整処理もしてないのに、勝手にプログラムが
    一つの伝送データを小分けにして、処理を繰り返してくれる様子をきっちり
    伝えなくては本当に理解しているとは思えません。

    記事を完成させた為だけに手を抜かないで下さい。

    • yield使うだけで、何の調整処理もしてないのに、勝手にプログラムが 一つの伝送データを小分けにして、処理を繰り返してくれる様子をきっちり 伝えなくては本当に理解しているとは思えません。⇦読みづらい! says:

      否定するなら、参照先の一つでも貼るのが道理では?

  9. とってもわかりやすかった!そして「はー?つか・・う・・価値・・・・・?」と疑問だったのが解消できました!
    メモリ節約を目指して使おう!
    ありがとうございました!

コメントはお気軽に