毎日Learning

学んだことを共有します

エキスパート 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の回数と、ループの回数が減らせるなー。うむ。使うなこれ。