LoginSignup
0
0

More than 5 years have passed since last update.

回り道Python(1)

Posted at

リストのコピーにハマる

Pythonでリストの複製を行おうと思って以下のようなコードを書いてハマる。

wrong1.py
sequence = [2, 3, 5, 7, 11, 13]
subsequence = sequence
subsequence.remove(13)
print(sequence)
print(subsequence)

期待していた実行結果は

[2, 3, 5, 7, 11, 13]
[2, 3, 5, 7, 11]

なのだが、実際の結果は

[2, 3, 5, 7, 11]
[2, 3, 5, 7, 11]

ハテ? removeしたsubsequenceの方はともかく、なんでsequenceまで要素13が削除が削除されたの?

理由が分からなくて調べるとすぐに判明。subsequence = sequenceというのが誤りで、これだとsubsequenceのIDをsequenceのIDで上書きしてしまう。つまり、subsequenceが指し示しているものと、sequenceが指し示しているものが、同一のものになるのだそうだ。だから、subsequenceにsequenceのコピーを作って内容を書き換えたつもりだったが、sequenceの内容そのものを書き換えていたのだ。

この辺は、C言語のポインタで出てくるような話に似ている。関数呼び出しの場合に参照渡し(アドレス渡し?ポインタ渡し?)すると呼び出し元の変数にアクセスできるようになるものだ。swap()関数のようなものをCで書く場合に良く例として挙げられるものだ。

ちなみに、上のPythonコードを期待通りに動作させる場合は、リストのIDをコピーするのではなく各要素をコピーするようにスライス[:]を付けてあげると良いのだそうだ。

correct1.py
sequence = [2, 3, 5, 7, 11, 13]
subsequence = sequence[:]
subsequence.remove(13)
print(sequence)
print(subsequence)

ただし、このコピー操作はとても遅いのか、数万個要素のリストコピーを数万回のループで処理させていたらとても時間がかかっていたのに、その分を見直して削除したら途端に早くなった。長い系列処理で、こういうコードを繰り返し実行するのは避けるべきだ。

0
0
0

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
0
0