Python3で引っかかるところ~リストとイテレータ~
mapやzipがリストではなくイテレータを返すようになったので、挙動がややこしい。
>>>a = [10, 20, 30] >>>b = [1, 2, 3] >>>z = zip(a, b) >>>list(z) [(10, 1), (20, 2), (30, 3)] >>>list(z) [] >>>list(z) []
zip(a, b)がリストではなくイテレータオブジェクトであり、それにlist関数を適用している。
1回listを適用した時点でイテレータが終了するので、2回目以降listを適用しても戻り値は空。
>>>a = [10, 20, 30] >>>b = [1, 2, 3] >>>list(zip(a, b)) [(10, 1), (20, 2), (30, 3)] >>>list(zip(a, b)) [(10, 1), (20, 2), (30, 3)] >>>list(zip(a, b)) [(10, 1), (20, 2), (30, 3)]
この場合、毎回新しいイテレータオブジェクトzip(a, b)を生成しているので、戻り値は期待通り。
>>>a = [10, 20, 30] >>>b = [1, 2, 3] >>>z = list(zip(a, b)) >>>z [(10, 1), (20, 2), (30, 3)] >>>z [(10, 1), (20, 2), (30, 3)] >>>z [(10, 1), (20, 2), (30, 3)]
この場合、イテレータzip(a, b)をlistに変換したものを変数zに保存しているので、zの値は変わらず、出力は期待通り。
>>>a = range(5) >>>list(a) [0, 1, 2, 3, 4] >>>list(a) [0, 1, 2, 3, 4] >>>list(a) [0, 1, 2, 3, 4]
はぁ?
Python3だとrange関数はリストではなくイテレータを返すはずなので、2回目以降のlist(a)は空になるんじゃないの?
何で?
<追記>
公式リファレンスを見たが、rangeは組み込み関数ではなく組み込み型、クラスだった模様。
それにイテレータオブジェクトというわけではないようだ。と思うしかない。xrangeと統合されてメモリ使用効率がよくなっただけ。
と考えないと↓の挙動との違いが説明できないし。
>>>a = iter([1, 3, 5]) >>>list(a) [1, 3, 5] >>>list(a) [] >>>list(a) []