見出し画像

Python ジェネレーター関数の備忘録

Pythonジェネレーター関数を調べて見た
 spaCyの公式解説動画「Intro to NLP with spaCy」を見ていたら、見たことが無いPython構文を書いていて、「うん? あれ何?」ってなった。
 動画ではJupyter Notebookで実行しながら実演していたが、spaCyの内容よりも知らない構文が気になって頭に何も入らなくなってしまった。w

Pythonジェネレーター関数
 画面を見ながら模写してsyntax errorを含む試行錯誤させているうちに、構文自体がPythonのジェネレーター関数であることが分かった。
 そこで、ジェネレーター関数の細かい日本語の説明では「Pythonのイテレータとジェネレータ」で見て欲しいのだけど、動画ではジェネレーター関数のyieldを全く使っていなかった。
 画面の記述は・・・

d = (text for text in texts if text == 'bbb')

 こんな雰囲気の構文だったので、調べる起点が無くVisual Studio Codeでデバッグモードで変数を調べても意味が良く分からず調べていたらやっとジェネレーター関数に辿り着いた。
 先のサイトではジェネレーター関数はreturnの代わりにyeildを使うってことを説明しているのだけれど、ジェネレーター関数を使うメリットが全く理解できなかった。
 次に別のサイト「Pythonのジェネレーターってなんのためにあるのかをなるべく分かりやすく説明しようと試みた」の文中に『リスト全体をメモリ内に保持するのが難しい、かつ不要なとき』と書いていて、やっとなるほどと理解した。
 つまり、NLP(natural language processing)等では大規模のコーパスを使うことが多いため、メモリを効率的に利用するために使用していることが分かった。spaCyの説明動画では、トレーニングデータをpandasで取り込み該当する条件の文を取り出してって処理の途中の説明だったのだ。そのため、1GByteのデータで該当する条件のlistデータが仮に500MByteあったとするとメモリ中に大量に取り込まれてしまう。そうでなくてもDeep Learningで使用するメモリが多くなる傾向にあるため、使用するメモリの削減を図りたいという訳だったのだろう。

メモリ解放タイミングは?
 目的は理解できたのだが、実際にメモリ解放されるタイミングはいつなのだろうか?
 知らなくてもコードは書けるのだが、知っている方がより効率の良いコードが書けるはずだ。では、どのタイミングでジェネレーター関数のメモリ解放が行われるのかを調べてみた。

# ジェネレーターのテスト
texts = ['aaa', 'bbb', 'ccc']
d = (text for text in texts if text == 'bbb')
print('1st:' + str(list(d)))
print('2nd:' + str(list(d)))    # ジェネレーター生成変数の生存は1回のみ
> & ...anaconda3/python.exe "d:../test01.py"
1st:['bbb']
2nd:[]

 上記の通り、1回しか利用されないという結果になった。Javaのガベージコレクタよりは開放されるという観点からは非常にわかり易い。


この記事が気に入ったらサポートをしてみませんか?