Pythonのイテレータで無限ループしてしまった話と解決策3つ
Pythonのイテレータって遅延評価で、それは普通いいことなんですけど、うっかり無限ループしてしまいました。
問題
リスト l
の各要素に100を足して l
にappendするつもりで以下のコードを書きました。
l.extend(map(lambda i: i+100, l))
map()
はイテレータを作り、 extend()
により評価されるたびに第2引数の l
(か iter(l)
)の次の要素がyieldされるわけですが、 l
は extend()
により長さが増えていくので、いつまでも終わりにたどり着かないわけですね。
解決策
リストをコピーする
extend()
により伸びていくリストではなく、それを呼ぶ前のスナップショットをイテレートします。
l.extend(map(lambda i: i+100, l[:]))
イテレータを先に評価する
extend()
より先に map()
の評価を終わらせます。リスト内包でもいいです。
l.extend(list(map(lambda i: i+100, l)))
イテレータに終わりを設ける
extend()
する前の長さで終わりにします。
from itertools import islice l.extend(map(lambda i: i+100, islice(l, len(l))))