Python でリストをコピーする方法 (浅いコピーと深いコピー)

Python でリストをコピーする方法を学びます。リストのスライス、copy() メソッド、リスト コンストラクターを調べて、浅いコピーと深いコピーの違いをマスターします。

エディターでこのソリューションを試してください

概要

Python では、リストは変更可能なオブジェクトであり、変数は実際の値ではなく、これらのオブジェクトへの参照をメモリ内に保持します。これは、リストを新しい変数に割り当てる場合 (例: 「list_b = list_a」)、両方の変数がまったく同じリストを参照することを意味します。 `list_b` を通じて行われた変更は、直ちに `list_a` に影響します。この副作用を回避するには、リストの明示的なコピーを作成する必要があります。

Python には、リストの浅いコピーを作成する方法がいくつか用意されています。浅いコピーは、元のリストにある要素への参照を含む新しいリストを構築します。一般的な方法には、組み込みリスト `.copy()` メソッドの使用、リスト スライス `list_a[:]` の使用、またはリストを `list()` コンストラクターに渡すことが含まれます。これらはすべて新しいリスト コンテナーを作成し、要素を個別に追加または削除できるようにします。

ただし、リストにネストされた変更可能なオブジェクト (リストや辞書など) が含まれている場合、浅いコピーでは外側のコンテナーのみが複製されます。ネストされたオブジェクトは共有されたままになります。コピー内のネストされたリストを変更すると、元のリストが変更されます。これを防ぐには、`copy` モジュールの `deepcopy()` 関数を使用してディープ コピーを実行する必要があります。これにより、階層内のすべてのオブジェクトが再帰的に複製されます。

コードと実行の出力

このコードは、参照割り当てトラップ、list.copy() を使用した浅いコピー、および copy モジュールを使用したネストされたリストの深いコピーを示します。

import copy

# 1. The assignment reference trap (Not a copy!)
original = [1, 2, 3]
reference = original
reference.append(99)
print("Reference modification affects original:", original)

# Reset list
original = [1, 2, 3]

# 2. Creating a shallow copy (using list.copy())
shallow_copy = original.copy()
shallow_copy.append(100)
print("\nOriginal:", original)
print("Shallow copy:", shallow_copy)

# 3. The nested list limitation of shallow copies
nested = [[1, 2], [3, 4]]
shallow_nested = nested.copy()
shallow_nested[0].append(99) # Modifying nested list
print("\nOriginal nested:", nested)
print("Shallow nested copy:", shallow_nested)

# 4. Creating a deep copy
nested_original = [[1, 2], [3, 4]]
deep_copy = copy.deepcopy(nested_original)
deep_copy[0].append(99)
print("\nOriginal nested:", nested_original)
print("Deep copy (completely independent):", deep_copy)
端子出力
Reference modification affects original: [1, 2, 3, 99]

Original: [1, 2, 3]
Shallow copy: [1, 2, 3, 100]

Original nested: [[1, 2, 99], [3, 4]]
Shallow nested copy: [[1, 2, 99], [3, 4]]

Original nested: [[1, 2], [3, 4]]
Deep copy (completely independent): [[1, 2, 99], [3, 4]]

段階的な実装

  • my_list.copy() または my_list[:] を使用して、フラット リスト構造の浅いコピーを作成します。
  • 独立したコレクションが必要な場合は、copy_list = my_list のような参照割り当てを避けてください。
  • コピー モジュールをインポートし、ネストされた可変構造を含むリストに copy.deepcopy(my_list) を使用します。
  • パフォーマンスとメモリ使用量を最適化するためにデータ構造を理解してください。

よくある質問

浅いコピーと深いコピーの違いは何ですか?

浅いコピーは最も外側のコンテナをコピーしますが、ネストされた可変オブジェクトを参照します。ディープ コピーでは、すべてのネストされたコンテナーとオブジェクトが再帰的に複製され、完全に分離されたデータ構造になります。

リストのスライス (list[:]) は list.copy() よりも高速ですか?

どちらも内部で最適化された C 操作を実行するため、パフォーマンスは実質的に同じです。一般に、読みやすさを考慮すると、 list.copy() を使用することが推奨されます。

関連トピック

推奨される Python リソース

関連するインタラクティブなチュートリアル、チートシート、コード比較で知識を深めてください。