以下は整数のリストと、前後の要素の差を計算するソースコードです。
# 整数のリスト >>> data = [1, 4, 2, 8, 5, 7] # 差を計算 >>> for i in range(1, len(data)): ... print(data[i] - data[i-1])
上のループ文の書き方は、Pythonicさがあまり感じられませんね。[]に index値を入れて走査するのは Python 的ではありません。
Python らしいループ文は以下のようになります。
>>> for i, j in zip(data[1:], data): ... print(i - j)
zip とスライスを使い、かなりPythonicになりました。
しかし、この書き方には問題があります。スライスはコンテナの複製を作成します(いわゆるディープコピー)。このため、 data のサイズが大きい場合には、data[1:] が大きなメモリ負荷となる可能性があります。
data を複製するのではなく data からイテレータオブジェクトを作成すれば、この問題は解消されます。イテレータオブジェクトを利用する方法は以下のようになります。
>>> n = iter(data) >>> n.__next__() >>> for i, j in zip(n, data): ... print(i - j)
メモリ負荷の問題は解消しましたが、ループ文のための準備が2行あり、あまりCoolな書き方ではありませんね。ここでは省略していますが、安全のためには data が空リストだった場合の処理を追加する必要があります。その処理も追加すれば、ますますCoolではなくなります。
ここで、ようやく itertools.islice の出番です。ここまで述べてきた問題を全て解決するのが、itertools.islice です。
その使い方は以下のようになります。
>>> from itertools import islice >>> for i, j in zip(islice(data, 1, None), data): ... print(i - j)
[]でのリストへのアクセスがなくなり、余計なメモリ負荷が無く、ループ文自体を1行で書ける。まさにCoolでPythonicな書き方だと思います。
0 件のコメント:
コメントを投稿