Code Fix

上級

= で複製したつもりが同じリストを指している(浅いコピー)

= はリストや辞書の複製ではなく、同じオブジェクトを指す別名を作るだけです。片方を変更すると、もう片方にも影響します。

なぜエラーが出ないのか

出力: [1, 2, 3, 4]
(エラーなし)
Pythonは何も報告しません。文法として正しいためです
出力: [1, 2, 3, 4]
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  original = [1, 2, 3]
 2  copy = original       
                  ^
 3  copy.append(4)
 4  print(original)
出力: [1, 2, 3, 4]期待: [1, 2, 3] (エラーにはなりません)

= は同じリストを指す別名を作るだけで、複製ではありません。独立したコピーが欲しい場合は.copy()やスライスを使います。

直し方: original を original.copy() にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  user = {"name": "Tom", "age": 20}
 2  backup = user        
                   ^
 3  backup["age"] = 99
 4  print(user)
出力: {'name': 'Tom', 'age': 99}期待: {'name': 'Tom', 'age': 20} (エラーにはなりません)

「バックアップ」のつもりで代入しても、元の辞書と同じ実体を指したままです。バックアップ後の変更が元データにも反映されてしまいます。

直し方: user を user.copy() にします。

この問題を解いてみる →

パターン3

 1  team = ["Tom", "Anna"]
 2  roster = team       
                  ^
 3  roster.append("Ken")
 4  print(team)
出力: ['Tom', 'Anna', 'Ken']期待: ['Tom', 'Anna'] (エラーにはなりません)

名簿を複製して片方だけ変更するつもりが、両方に反映されてしまう典型例です。

直し方: team を team.copy() にします。

この問題を解いてみる →

パターン4

 1  settings = {"volume": 5}
 2  temp = settings        
                   ^
 3  temp["volume"] = 0
 4  print(settings)
出力: {'volume': 0}期待: {'volume': 5} (エラーにはなりません)

設定値を一時的に変えるつもりが、元の辞書ごと書き換えてしまう典型例です。

直し方: settings を settings.copy() にします。

この問題を解いてみる →

パターン5

 1  queue = [1, 2, 3]
 2  snapshot = queue       
                     ^
 3  snapshot.pop()
 4  print(queue)
出力: [1, 2]期待: [1, 2, 3] (エラーにはなりません)

スナップショットのつもりで代入しても同じ実体です。片方から取り除くと、元のキューからも消えてしまいます。

直し方: queue を queue.copy() にします。

この問題を解いてみる →

よくある誤解

他の言語で値型として扱われるデータ(配列など)の感覚で = を使うと、Pythonでは参照が共有されるだけだと気づかずハマります。

実務での勘所

コピーには実は3段階あります。=は複製ではなく別名(同じオブジェクトを指す名札を増やすだけ)です。list.copy()やlist[:]、copy.copy()は「浅いコピー」で、外側のリストは新しく作られますが、中に別のリストや辞書が入れ子になっている場合、その内側のオブジェクトまでは複製されず共有されたままです。入れ子の中身まで完全に独立させたい場合は、copy.deepcopyという再帰的にすべてを複製する関数が必要です。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)