重要な点は、リスト内包表記が新しいリストを作成することです。ジェネレーターは反復可能なオブジェクトを作成します。これは、ビットを消費するときにオンザフライでソースマテリアルを「フィルター」します。
「hugefile.txt」という2TBのログファイルがあり、「ENTRY」という単語で始まるすべての行の内容と長さが必要だとします。
したがって、リスト内包表記を作成することから始めます。
logfile = open("hugefile.txt","r")
entry_lines = [(line,len(line)) for line in logfile if line.startswith("ENTRY")]
これにより、ファイル全体が丸められ、各行が処理され、一致する行が配列に格納されます。したがって、このアレイには最大2TBのコンテンツを含めることができます。これは大量のRAMであり、おそらくあなたの目的には実用的ではありません。
代わりに、ジェネレータを使用してコンテンツに「フィルタ」を適用できます。結果の反復を開始するまで、実際にはデータは読み取られません。
logfile = open("hugefile.txt","r")
entry_lines = ((line,len(line)) for line in logfile if line.startswith("ENTRY"))
まだ1行もファイルから読み込まれていません。実際、結果をさらにフィルタリングしたいとします。
long_entries = ((line,length) for (line,length) in entry_lines if length > 80)
まだ何も読み込まれていませんが、ここでは、希望どおりにデータを操作する2つのジェネレータを指定しました。
フィルター処理された行を別のファイルに書き込みます。
outfile = open("filtered.txt","a")
for entry,length in long_entries:
outfile.write(entry)
次に、入力ファイルを読み取ります。私たちのようfor
ループが追加の行を要求し続け、long_entries
発電機からのラインを要求しentry_lines
、その長さが80文字を超えるものだけを返す、発電機。そして今度は、entry_lines
ジェネレーターは(示されているようにフィルターされた)行をlogfile
イテレーターイテレーターがファイルを読み取ります。
したがって、完全に入力されたリストの形式でデータを出力関数に「プッシュ」する代わりに、必要な場合にのみ出力関数にデータを「プル」する方法を提供します。私たちの場合、これははるかに効率的ですが、それほど柔軟ではありません。ジェネレーターは一方向、ワンパスです。読み込んだログファイルのデータはすぐに破棄されるため、前の行に戻ることはできません。一方、データを使い終わったら、データを保持する必要はありません。
[exp for x in iter]
だけのために砂糖ことlist((exp for x in iter))
?または実行の違いはありますか?