ちょっくら面白い動きをしたので、晒してみる。
ループの中でコンテナを書き換えても、ループの終了判定やらには影響しないのかなーと思ったが、一歩間違えると無限ループ化も夢じゃないようだ。
>>> container = range(3) >>> for i in container: ... print 'i = %d' %i ... print 'container = %s' %container ... i = 0 container = [0, 1, 2] i = 1 container = [0, 1, 2] i = 2 container = [0, 1, 2] >>>
意図通りの動きです。
>>> container = range(3) >>> for i in container: ... print 'i = %d' %i ... container = 'container = %d' %i ... print 'container = %s' %container ... i = 0 container = container = 0 i = 1 container = container = 1 i = 2 container = container = 2 >>>
ループの中でコンテナを書き換えてみましたが、何事もなかったかのようにループが回りました。
>>> container = range(3) >>> for i in container: ... print 'i = %d' %i ... container.append(i+3) ... print 'container = %s' %container ... if i == 10: ... break ... i = 0 container = [0, 1, 2, 3] i = 1 container = [0, 1, 2, 3, 4] i = 2 container = [0, 1, 2, 3, 4, 5] i = 3 container = [0, 1, 2, 3, 4, 5, 6] i = 4 container = [0, 1, 2, 3, 4, 5, 6, 7] i = 5 container = [0, 1, 2, 3, 4, 5, 6, 7, 8] i = 6 container = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] i = 7 container = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] i = 8 container = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] i = 9 container = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12] i = 10 container = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] >>>
break しなかったら、無限ループに突入ですwww
2番目の例と、3番目の例が混在するのが面白いです。
、、、と思って、他の例をやってみました。
>>> container = range(3) >>> for i in container: ... print 'i = %d' %i ... container[i] = 100 ... print 'container = %s' %container ... i = 0 container = [100, 1, 2] i = 1 container = [100, 100, 2] i = 2 container = [100, 100, 100] >>>
ちゃんと回りますねー
じゃー↓はどうだ!
>>> container = range(10) >>> for i in container: ... print 'i = %d' %i ... container.remove(len(container)-1) ... print 'container = %s' %container ... i = 0 container = [0, 1, 2, 3, 4, 5, 6, 7, 8] i = 1 container = [0, 1, 2, 3, 4, 5, 6, 7] i = 2 container = [0, 1, 2, 3, 4, 5, 6] i = 3 container = [0, 1, 2, 3, 4, 5] i = 4 container = [0, 1, 2, 3, 4] >>>
ここまでを簡単にまとめると、、、
- ループの終了判定は都度コンテナの内容を参照してやっている。
- コンテナを参照する際のポインタは、カウンタとは独立した別の”何か”らしい。
- 参照されるコンテナの内容が変更されていても、ループ用の(内部的な)ポインタの指し先が関係なければ、普通にループは回るらしい。
で、も、ね。
>>> container = range(10) >>> for i in container: ... print 'i = %d' %i ... container = range(3) ... print 'container = %s' %container ... i = 0 container = [0, 1, 2] i = 1 container = [0, 1, 2] i = 2 container = [0, 1, 2] i = 3 container = [0, 1, 2] i = 4 container = [0, 1, 2] i = 5 container = [0, 1, 2] i = 6 container = [0, 1, 2] i = 7 container = [0, 1, 2] i = 8 container = [0, 1, 2] i = 9 container = [0, 1, 2] >>>
これが動くということは、ループで使用しているcontainerと内部で使用しているcontainerが別インスタンスという認識でOKかなぁ。
つまり、、、
- 下の例だと、ループに使っているcontainer が変更される。
>>> for i in container: ... container.append(i+3)
>>> for i in container: ... container = range(3)
- この場合、元のcontainer のインスタンスが残っている(ただしcontainer のポインタ先は新しい range(3) のインスタンスなので、問題なく動く。
- 、、、が、ガベージコレクションのタイミングによっては、危ない。
- (でも、実はforループが参照しているから、元のcontainerインスタンスはガベージコレクション対象ではないようにも見える。)
こんなところでどうでしょう。(間違いがあったら、コメントをお願いしますね。)
コードとして、どういう場面で有効に使えるか、、、というのは、甚だ疑問だが、面白い。
まぁ、そもそもこんな危険が危ないwコードは書かないようにしませう。