リストをコピーする時に注意するポイントがあります。
リストのコピーにはそのデータをコピーしたものがもう一つの独立したリストとして扱える形になったり、コピーしてもコピー元のデータが変わるとコピー先のデータも変わってしまうパターンがあります。
これはメモリの内部的な参照先が同じデータであるか、独立したものであるかの違いになります。
このあたりに注意してリストのコピーをみていきましょう。
リストをコピーする
リストのコピーの方法はいろいろあります。
まず、元となるリストを用意しておきましょう。
a = ["YouTube", "Instagram", "LINE"]
このリストを使ってコピーをしていきます。
代入(=)を使ってコピーする
まずはイコール(=)を使って、リストを他の変数に代入してみます。
コードをこうしてみましょう。
a = ["YouTube", "Instagram", "LINE"]
b = a
aをbに代入して出力します。
対話型シェルで順に実行してみるとこうなります。
bにaと同じリストが入って出力されているのがわかります。
ここで、これに続けてリストaの中身を変更する処理をしてみます。3つ目の「LINE」を「Tik Tok」にインデックスを使って変更してみます。
a[2] = "Tik Tok"
このコードで置き換えができるのはわかりますよね。
ではこれを実行してみます。
aのリストの中身が変更されました。
この時、bを続けて出力してみるとどうなるでしょうか。
このように、bは何も操作していないのに中身が変わってしまいました。
これは、aもbもメモリ内の同じところに格納されている同一のデータを参照しているからで、イコールを使うとこういう処理になるというわけです。
どちらも同じところを見ているということなので、ここでbを操作してもaも同じようになります。
bの先頭のデータを変えただけで、aの先頭のデータも変わっていますね。
aもbも同じデータを参照しているかどうかは、id()を使って調べることができます。続けて、a、bのidを調べてみるとこうなります。
どちらも同じ数字が表示されていますね。これで、どちらも同じデータを参照しているということがわかります。
copy()を使ってコピーする(list関数とスライスも)
では、コピーしたものが同じデータを参照するものではなくて、全く独立した別のデータとして扱えるようにするにはどうすればいいのでしょうか。
それはcopy()を使うことで可能になります。
リスト.copy()の形で利用します。
同じリストを使ってコードを書いてみましょう。
ついでに、同じことができるlist()とスライス[:]も使って合わせてやってみます。
a = ["YouTube", "Instagram", "LINE"]
b = a.copy()
c = list(a)
d = a[:]
これを実行するとこうなります。
全てaのコピーができています。
ここでa、b、c、dをid()で調べてみるとどうなるでしょうか。続けてやってみるとこうなりました。
それぞれの数値が全て違うのがわかりますね。ということは、お互いにどれも独立したリストになっているということがわかります。
これがイコール(=)で代入することとの違いです。
まとめ
リストをコピーするには単にデータを参照するだけの方法と、独立したリストとしてコピーを作るという方法があります。
イコール(=)を使って代入することでコピーをすると、同じデータ元を参照するリストが出来上がります。これはデータを操作すると、どちらにも変更が反映されます。
copy()、list()、スライス[:]を使ってリストをコピーをすると、独立した別のデータとしてリストが作成されます。
データが同じものか、独立したものかを調べるには、id()を使えば確認することができます。