【Python】直接代入/シャローコピー/ディープコピーの違い

雑学

更新月:2024/12
Pythonの変数への代入における、直接代入/シャローコピー/ディープコピーの違いについて理解する記事になります。

シャローコピーとディープコピーの違い

1. 直接代入するケース

original_list = [1, 2, [3, 4]]

# 直接代入
assigned_list = original_list

# 変更
assigned_list[0] = 99
assigned_list[2][0] = 999

# 結果を表示
print("original_list:", original_list)  # [99, 2, [999, 4]]
print("assigned_list:", assigned_list)  # [99, 2, [999, 4]]

説明:

  • assigned_list = original_list」とした時点で、assigned_listoriginal_list は同じオブジェクトを指し示します。
  • そのため、assigned_list で変更を加えると、original_list も影響を受けます。
  • 特に、内側のリスト([3, 4])も両方で共有されているため、assigned_list[2][0] = 999 を変更したとき、original_list も変更されます。

2. シャローコピーを用いるケース

import copy

original_list = [1, 2, [3, 4]]

# シャローコピーを作成
shallow_copy = original_list.copy()

# 変更
shallow_copy[0] = 99
shallow_copy[2][0] = 999

# 結果を表示
print("original_list:", original_list)  # [1, 2, [999, 4]]
print("shallow_copy:", shallow_copy)    # [99, 2, [999, 4]]

説明:

  • shallow_copy = original_list.copy()で、シャローコピーを作成します。
  • シャローコピーでは、リストの要素(1, 2, [3, 4])がコピーされますが、内側のリスト([3, 4])の参照は共有されます。
  • そのため、shallow_copy[2][0] = 999 を変更すると、original_list の中の内側のリストも影響を受けます。
  • しかし、リストの最初の要素 0 を変更しても、original_list[0] は変わりません。

3. ディープコピーを用いるケース

import copy

original_list = [1, 2, [3, 4]]

# ディープコピーを作成
deep_copy = copy.deepcopy(original_list)

# 変更
deep_copy[0] = 99
deep_copy[2][0] = 999

# 結果を表示
print("original_list:", original_list)  # [1, 2, [3, 4]]
print("deep_copy:", deep_copy)          # [99, 2, [999, 4]]

説明:

  • deep_copy = copy.deepcopy(original_list)で、ディープコピーを作成します。
  • ディープコピーでは、元のリストとその中のオブジェクトをすべて新しくコピーします。
  • そのため、元のリストとディープコピーはまったく独立したオブジェクトになります。
  • したがって、deep_copy[0] = 99deep_copy[2][0] = 999 を変更しても、元のリストには影響を与えません。

まとめ:直接代入、シャローコピー、ディープコピーの違い

操作 直接代入 シャローコピー ディープコピー
変数間の関係 同じオブジェクトを参照 新しいリストオブジェクトが作成され、内部の参照は共有 新しいリストとその中身(再帰的に)もすべて新しくコピー
内部オブジェクト(リスト等)の影響 変更が両方に影響を与える 内部オブジェクトは参照を共有、変更が影響を与える 完全に独立、変更が元のオブジェクトに影響しない
変更時の挙動 両方に反映される ミュータブルな内部オブジェクトに変更が反映される 完全に独立しているので、元のオブジェクトに影響を与えない

直感的な理解のためのポイント

  • 直接代入では、2つの変数が同じオブジェクトを指し示しているため、どちらを変更しても両方に影響があります。
  • シャローコピーでは、リスト自体のコピーは作成されますが、その中のミュータブルなオブジェクト(例えば、リストや辞書など)は参照が共有されるため、内部のオブジェクトの変更は元のリストにも影響を与えます。
  • ディープコピーでは、オブジェクトとその中身が全て新しくコピーされるため、元のオブジェクトとディープコピーは完全に独立しています。

補足:シャローコピー&イミュータブルで影響を与えない理由

シャローコピーしたリストで数値や文字列のようなイミュータブルなオブジェクトを示す要素の内容を変更(直接代入)してもコピー元には影響を与えません。コピー先の要素として持つ参照値を別で作られた新規イミュータブルオブジェクトの参照値に書き換えるに過ぎないためです。

関連記事

外部リンク

生成AIメモ

  • 利用AI:ChatGPT 4o mini、一部利用
  • プロンプト1:pythonの「シャローコピー」の説明を初学者に向けた内容でお願いします。「参照値の値渡し」を内容に含めて、文を組み立ててほしいです。
  • プロンプト2:説明をまとめて欲しいです。
    ・コピーメソッドを使わず、直接代入するケース
    ・シャローコピーを用いるケース
    ・ディープコピーを用いるケース
    差が明確になる直感的にわかりやすい記述でお願いします。
  • プロンプト3:先程の内容をhtml形式(style使用せず)で出力してほしいです。

内容チェック済。