エキスパート Python プログラミング メモ Vol.3
2.2.3 ジェネレータ式
ジェネレータも、リストの内包表記と同じようなショートカットがあるとのこと。
まじかよ。そんなんして良いのかよ。おなかいっぱいだよ。
>>> iter = (x**2 for x in range(10) if x % 2 == 0) >>> for el in iter: ... print(el) ... 0 4 16 36 64
こ、これは!!
過去に以下のコードを書いたことあるな。
import csv reader = csv.reader(open("hoge.csv", "r")) for a in [row for row in reader if row]: print a
みたいな。CSVファイルを読み込んで、空行じゃなきゃループせいみたいな処理だったかと。
使い捨てのスクリプトやったし、速度とかどうでも良かったし、えーやって思って書いたけど、これはジェネレータ式に置き換えられるんだな。
うむ。
2.2.4 itertoolsモジュール
イテレータがPythonに追加されたときに、あらかじめ一般的な使用パターンを実装した新しいモジュールも追加されました。
このモジュールは、C言語で実装されている効率のよいイテレータを提供します。
と、いうことは、itertoolsで提供することと同じことは、実装すんなよーってことだな。
islice : ウィンドウイテレータ
isliceはシーケンスのサブグループに対するイテレータを返します。
シーケンスのサブグループ。。。う、うん。これのイテレータを返すのね。よし。使ってみよ。
>>> [a for a in itertools.islice(range(10), 0)] [] >>> [a for a in itertools.islice(range(10), 1)] [0] >>> [a for a in itertools.islice(range(10), 3)] [0, 1, 2] >>> [a for a in itertools.islice(range(10), 3, 4)] [3] >>> [a for a in itertools.islice(range(10), 3, 5)] [3, 4] >>> [a for a in itertools.islice(range(10), 3, 100)] [3, 4, 5, 6, 7, 8, 9] >>> [a for a in itertools.islice(range(10), 3, None)] [3, 4, 5, 6, 7, 8, 9]
なるほどー。これって、下のコード書くと同じ結果やな。
>>> [a for a in range(10)[3::]] [3, 4, 5, 6, 7, 8, 9]
これは…どうなんやろ。使い分けの基準が分からんなー。コード的に短かく書けるのは、後者やな。
tee : 前後方イテレータ
イテレータは、動作時に使用したシーケンスを消費していきます。後戻りすることはできません。
teeは、1つのシーケンスで複数のイテレータを実行するためのパターンを提供します。
あるイテレータを最初に実行して、もう1つのイテレータを保持することで、そのデータを再処理するときに役立ちます。
>>> a, b = itertools.tee(range(10)) >>> [v for v in a] [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> [v for v in b] [1, 2, 3, 4, 5, 6, 7, 8, 9]
なるほど。これは使いそう。過去に、ログ出力の関係で、ファイルを開いて行数だけ数えて、もっかい開いて内容を処理するようなコードを書いた記憶がある。
こういう場合に使えるなー。IOの回数と、ループの回数が減らせるなー。うむ。使うなこれ。