Python実践入門 9章
ジェネレータ
ジェネレータ概要
for文で使えるイテラブルオブジェクト
要素が求められるたびに生成を行うのでメモリ効率が良い
code: generator.py
def inf(n):
while True:
for i in inf(3)
print(i)
# 3
# 3
# 3
ジェネレーターはジェネレータ関数かジェネレータ式で作れる
ジェネレータ関数は上のような関数内でyieldが呼ばれるもの
ジェネレーター式は、リスト内包表記と同じ呼び方だけど、[]でなく、()で閉じる
イテラブルなオブジェクトなので、必要になるまで計算されない
code: generator-siki.py
>> l
>> g = (i**2 for i in x)
>> g
<generator object <genexpr> at 0x1032c7200>
>> for i in g:
... print(i)
...
1
4
9
ジェネレータの利用例
ファイルを1行ごと読み込むジェネレータ関数を作ることで、ファイルないの文字を全て大文字に変換して別のファイルに書き込むとかするときに、元のファイルサイズが大きくてもメモリを圧迫せずに処理ができる
最近だと機械学習やデータ分析などの大容量データ扱うときに、逐次処理で利用することが多い
リストを返す関数では積極的にジェネレータ使った方がいいらしい
デコレータ
関数やクラスに処理を追加できる機能
@で始まるやつ、アノテーション的な
関数の引数チェックや、関数の結果キャッシュとかを実装できる
よくあるやつ
@lru_cache, 指定した回数の呼び出しまではキャッシュが利用される
@dataclass, Frozen=Trueで渡して、インスタンスを作成後状態変更不可にできたりできる
コンテキストマネージャ
with文に対応したオブジェクト
open()とか
ブロック内に入る時と出るときに、処理を入れることができる(goでいうdeferとかに近いかもね)
try, finallyに近いかも
__enter__(), __exit__()で実装
デコレーターで簡単に作るのもできる
ネットワークやDBやらの接続処理の後処理系入れるのによく使われる
デスクリプタ
インスタンス変数のプロパティ、ガードなどの処理をクラスとしてまとめて複数クラスで再利用できるようにするらしい?