19
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

for for ∞ for python

Last updated at Posted at 2017-11-26

C言語とかはfor(;;)とかで無限ループできるらしいですが、pythonのfor文でも出来ます。気をつけて下さい。動作確認はpython3でやってますが、python2とかでも起きるはずです。
あと、普通に無限ループしたい場合はwhile True:を使ってください。

方法

for文が参照しているリストをループ内で増やす。

サンプルコード

from time import pause # これなしで無限ループを試す度胸ないです

# 参照するリストの初期化
loop = [0]

# 無限ループ
for i in loop:
    print(i)
    pause(0.5)
    loop.append(i+1)

適当なあたりで切り上げて下さい。

対策

ただループするつもりが、無限ループになっちゃった!というのはとても怖いので、対策をお伝えしておきます。

リストをコピーした上でfor文に渡して下さい。

# 有限ループ
for i in loop[:]:
    print(i)
    pause(0.5)
    loop.append(i+1)

注意:対策になってそうでなってない奴

loop2 = loop

# 無限ループ
for i in loop2:
    print(i)
    pause(0.5)
    loop.append(i+1)

これ、一旦loop2にコピーしているので問題なさそうに見えますが、loopに要素を追加すると、loop2にも追加されます。
代入はオブジェクトをコピーせず、オブジェクトを共有します。
下のは問題ありません。[:]をつけるとシャローコピーしてくれるので。

loop2 = loop[:]

# 有限ループ
for i in loop2:
    print(i)
    pause(0.5)
    loop.append(i+1)

リストのコピーについて

コメントを受けて調べ直したところ、[:]はシャローコピーとは違うことがわかりました。
4種類のリストのコピーとその違いを紹介します。

before = [[1,2,3], [4,5,6]]

以下の四つです。

  • そのまま代入
  • スライス([:])を使う
  • list()を使う
  • copy.deepcopyを使う

そのまま代入

after_eq = before

ここで、after_eqbeforeidを調べてみましょう

id(after_eq) == id(before)
# => True

これはどういうことかというと、リストはコピーされず、ひとつのリストを二つの変数から扱える状態です。
それが嬉しいかはわかりません。

スライス([:])やlist()を使う

この二つは結果が同じです。

after_sl = before[:]
id(after_sl) == id(before)
# => False

after_ls = list(before)
id(after_sl) == id(before)
# => False

このように、スライスやlist()を使うと全く別のリストがコピー出来たように思います。しかし、

id(after_sl[0]) == id(before[0])
# => True

id(after_ls[0]) == id(before[0])
# => True

となります。つまり、一階層だけコピーするシャローコピーと言うことです。
これがどういう意味かは、以下の例も参考にして考えてみて下さい。

zero = [[0]]
zeros = zero*3
print(zeros)
# => [[0], [0], [0]]
zeros[0][0] = '0'
print(zeros)
# =>[['0'], ['0'], ['0']]

copy.deepcopyを使う

1番安全なのは、標準ライブラリ内のcopy.deepcopyを使うことだと思います。

import copy

after_dc = copy.deepcopy(before)

id(after_dc) == id(before)
# => False

id(after_dc[0]) == id(before[0])
# => False

これこそがディープコピーというものです。

19
19
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?