= で複製したつもりが同じリストを指している(浅いコピー)
= はリストや辞書の複製ではなく、同じオブジェクトを指す別名を作るだけです。片方を変更すると、もう片方にも影響します。
なぜエラーが出ないのか
出力: [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)
= は同じリストを指す別名を作るだけで、複製ではありません。独立したコピーが欲しい場合は.copy()やスライスを使います。
直し方: original を original.copy() にします。
パターン2
1 user = {"name": "Tom", "age": 20} 2 backup = user ^ 3 backup["age"] = 99 4 print(user)
「バックアップ」のつもりで代入しても、元の辞書と同じ実体を指したままです。バックアップ後の変更が元データにも反映されてしまいます。
直し方: user を user.copy() にします。
パターン3
1 team = ["Tom", "Anna"] 2 roster = team ^ 3 roster.append("Ken") 4 print(team)
名簿を複製して片方だけ変更するつもりが、両方に反映されてしまう典型例です。
直し方: team を team.copy() にします。
パターン4
1 settings = {"volume": 5} 2 temp = settings ^ 3 temp["volume"] = 0 4 print(settings)
設定値を一時的に変えるつもりが、元の辞書ごと書き換えてしまう典型例です。
直し方: settings を settings.copy() にします。
パターン5
1 queue = [1, 2, 3] 2 snapshot = queue ^ 3 snapshot.pop() 4 print(queue)
スナップショットのつもりで代入しても同じ実体です。片方から取り除くと、元のキューからも消えてしまいます。
直し方: queue を queue.copy() にします。
よくある誤解
他の言語で値型として扱われるデータ(配列など)の感覚で = を使うと、Pythonでは参照が共有されるだけだと気づかずハマります。
実務での勘所
コピーには実は3段階あります。=は複製ではなく別名(同じオブジェクトを指す名札を増やすだけ)です。list.copy()やlist[:]、copy.copy()は「浅いコピー」で、外側のリストは新しく作られますが、中に別のリストや辞書が入れ子になっている場合、その内側のオブジェクトまでは複製されず共有されたままです。入れ子の中身まで完全に独立させたい場合は、copy.deepcopyという再帰的にすべてを複製する関数が必要です。