今回は、Pythonでリスト(list)をコピーする方法についてご紹介します。
リストをコピーする基本
Pythonでリストを複製したいとき、単純に「=」で代入すると同じオブジェクトを参照してしまい、変更が元のリストに反映されるという問題が発生します。
これを回避するためには、新たなリストを作成してコピーする仕組みが必要です。
Pythonでは、浅いコピー (shallow copy)と深いコピー (deep copy)という2つの手法があります。
用途やリストの構造によって、適切な方法を選択しましょう。
浅いコピー (shallow copy) の方法
浅いコピーはリストそのものを新たに作成しますが、リスト内に格納されている要素(特に可変オブジェクト)は元のリストと同じ実体を参照します。
そのため、ネストされたリストや辞書などを含むときは変更の影響が共有される点に注意が必要です。
以下に代表的な浅いコピーの方法を示します。
スライス構文を使う
リスト全体をスライスし、別のリストとしてコピーできます。
1 2 3 4 5 6 |
original_list = [1, 2, 3, 4] copied_list = original_list[:] # リスト全体をスライスしてコピー copied_list[0] = 100 print("original_list:", original_list) print("copied_list:", copied_list) |
original_list: [1, 2, 3, 4]
copied_list: [100, 2, 3, 4]
この例では、copied_listを変更しても、original_listは変化しません。
list() コンストラクタを使う
リストを引数に渡して新しいリストを作成できます。
1 2 3 4 5 6 |
original_list = [1, 2, 3, 4] copied_list = list(original_list) copied_list[1] = 200 print("original_list:", original_list) print("copied_list:", copied_list) |
original_list: [1, 2, 3, 4]
copied_list: [1, 200, 3, 4]
.copy() メソッドを使う
Python 3.3以降のリストにはcopy()メソッドが用意されています。
1 2 3 4 5 6 |
original_list = [1, 2, 3, 4] copied_list = original_list.copy() copied_list[2] = 300 print("original_list:", original_list) print("copied_list:", copied_list) |
original_list: [1, 2, 3, 4]
copied_list: [1, 2, 300, 4]
リスト内包表記を使う
リスト内包表記で要素をイテレーションし、新たにリストを作る方法です。
1 2 3 4 5 6 |
original_list = [1, 2, 3, 4] copied_list = [item for item in original_list] copied_list[3] = 400 print("original_list:", original_list) print("copied_list:", copied_list) |
original_list: [1, 2, 3, 4]
copied_list: [1, 2, 3, 400]
copyモジュールの copy() 関数を使う
標準ライブラリのcopyモジュールを用いて、浅いコピーを行います。
1 2 3 4 5 6 7 8 |
import copy original_list = [1, 2, 3, 4] copied_list = copy.copy(original_list) copied_list[0] = 999 print("original_list:", original_list) print("copied_list:", copied_list) |
original_list: [1, 2, 3, 4]
copied_list: [999, 2, 3, 4]
深いコピー (deep copy) の方法
深いコピーはリストの内部まで再帰的にコピーするため、ネストされたリストが含まれていても、新しいオブジェクトが作られます。
copyモジュールに含まれるdeepcopy()を使うのが一般的です。
1 2 3 4 5 6 7 8 9 |
import copy original_list = [[1, 2], [3, 4]] copied_list = copy.deepcopy(original_list) # 深いコピーではネストされた要素も別オブジェクトになる copied_list[0][0] = 999 print("original_list:", original_list) print("copied_list:", copied_list) |
original_list: [[1, 2], [3, 4]]
copied_list: [[999, 2], [3, 4]]
このように、深いコピー後に要素を変更しても、元のリストには影響しません。
よくある注意点とエラー
リストをコピーする際、特に以下の点に気をつけましょう。
- 可変オブジェクトを含む場合、浅いコピーはネストされているリストを共有する
- 不要なコピーはメモリ使用量を増大させるため、必要に応じたコピー手法を選ぶ
- deepcopy()は処理コストが高くなる可能性があるので、パフォーマンス面に配慮する
- copy()メソッドやスライス構文などを混在させると、想定外の挙動に陥る場合がある
特定のコピー手法でエラーが起こることは少ないですが、例えばモジュールの読み込み忘れ(import copyを忘れるなど)や誤った使い方をするとNameErrorなどの例外が発生する可能性があります。
まとめ
Pythonのリストコピーは、浅いコピーと深いコピーで挙動が大きく異なります。
要素や構造に合わせて適切な方法を使うことが重要です。
スライスや.copy()メソッドなど、使いやすい手段をマスターしておくと便利です。