Pythonでの辞書のコピーは、データ構造を扱う上で非常に重要な概念です。
今回は、不変オブジェクトと可変オブジェクトの違いを学びます。
そして、コピーした辞書に『追加』、『削除』、『変更』などの操作を加えた際に、元の辞書とコピーされた辞書がどの様な挙動をするのかを学んでいきます。
データの安全な操作を保証するために、辞書の適切なコピー方法を学びましょう。

- 不変オブジェクトと可変オブジェクトの違い
- 辞書の2種類のコピー方法について
- コピーする際の注意点
- まとめ

今回、コードはGoogle Colabを使用して書いています。
他のIDE(VS codeなど)を使用した場合、
うまく実行できるか分かりませんので、Google Colabを使用してコードを書いてみてください。
不変オブジェクトと可変オブジェクトの違い





さて、プログラミングでは、データをコピーして、新しいデータを加えることがよくあります。
でも、元のデータを保持したい場合は、どうすればいいですか?



コピーして、元のデータはそのままにしておく?



正解です!
ただ、Pythonの辞書では、元のデータをそのままにしておくためには、
『不変オブジェクト』と『可変オブジェクト』の違いに気を付けておかなければいけません。
不変オブジェクトとは?
不変オブジェクトはよく『紙の本』に例えられます。
紙の本は、一度印刷されるとその内容を変更することができません。
もし誤字を修正したい場合や追加の章を挿入したい場合、本の内容を直接書き換えることはできず、新しい版を印刷しなければなりません。
この新しい版は、修正された内容を持っていますが、元の本とは全くの別物です。
このように、不変オブジェクトは、一度作成されるとその状態を変更することができず、変更を加えるには新しいオブジェクトを作成する必要があります。
Pythonにおける不変オブジェクトの代表的な例
- 整数(int)
- 浮動小数点数(float)
- 文字列(str)
- タプル(tuple)
- 論理値(bool):TrueやFalseの論理値も不変です。
- フローズンセット(frozenset)
可変オブジェクトとは?
可変オブジェクトは、『電子書籍』によく例えられます。
電子書籍は、内容を簡単に編集・更新することができます。
誤字を修正したり、新しい章を追加したり、内容を削除したりすることが、元のファイル内で直接行われます。
変更後も、それは同じ電子書籍のファイルであり、新しいファイルを作成する必要はありません。
このように、可変オブジェクトは、作成後もその状態を変更することが可能です。
Pythonにおける代表的な可変オブジェクトの例
- リスト(list)
- 辞書(dict)
- セット(set)
- バイト配列(bytearray)
辞書の2種類のコピー方法について





辞書をコピーする際には、浅いコピーと深いコピーの2種類の方法があります。
浅いコピーについて
浅いコピーは『外見だけを新しくし、中身は元のものを共有する』ということです。
『可変オブジェクト』と『不変オブジェクト』で浅いコピーの扱い方も違います。
『可変オブジェクト』で浅いコピーをした場合
可変オブジェクトの場合、浅いコピーで行われる「追加」、「削除」、「変更」などの操作は、元の辞書に影響を及ぼします。
これは、可変オブジェクトへの参照が共有されているためです。
つまり、コピーした可変オブジェクトを操作した場合、コピー元の辞書も内容が変更されてオリジナルのものが存在しなくなるというこです。
実際にコード例を見てみましょう。
浅いコピーを使用する際には、辞書内の可変オブジェクト(リストや辞書など)への変更が元の辞書にも反映されることが分かります。
# Pythonでの浅いコピーにおける追加、削除、変更の操作のコード例
import copy
# 元の辞書を作成
original_dict = {
"フルーツ": ["apple", "banana", "cherry"],
"値段": {"apple": 100, "banana": 80, "cherry": 120}
}
# 浅いコピーを作成
shallow_copied_dict = copy.copy(original_dict)
# 追加:フルーツのリストにorangeを追加
shallow_copied_dict["フルーツ"].append("orange")
# 削除:値段の辞書からappleの価格を削除
del shallow_copied_dict["値段"]["apple"]
# 変更:bananaの価格を変更
shallow_copied_dict["値段"]["banana"] = 85
# 結果の表示
print("元の辞書:", original_dict)
print("浅いコピーの辞書:", shallow_copied_dict)
元の辞書: {'フルーツ': ['apple', 'banana', 'cherry', 'orange'], '値段': {'banana': 85, 'cherry': 120}}
浅いコピーの辞書: {'フルーツ': ['apple', 'banana', 'cherry', 'orange'], '値段': {'banana': 85, 'cherry': 120}}
import copy
copyモジュールをプログラムにインポートしています。
copyモジュールには、オブジェクトのコピーを作成するための関数です。
shallow_copied_dict = copy.copy(original_dict)
この行で、original_dict
の浅いコピーを作成しています。
『浅いコピー』の定義の仕方辞書 = copy.copy(コピーしたい辞書)
不変オブジェクトを浅いコピーした場合
不変オブジェクトの場合、浅いコピーで行われる「追加」、「削除」、「変更」などの操作は操作は元の辞書に影響しません。
つまり、コピーした不変オブジェクトを操作した場合、コピー元の辞書の内容は変更されずオリジナルのものが存在するというこです。
実際にコード例を見てみましょう。
浅いコピーを使用する際には、辞書内の不変オブジェクトへの変更が元の辞書には反映されないことが分かります。
import copy
# 元の辞書を作成
original_dict = {
"フルーツ名": "apple",
"価格": 100
}
# 浅いコピーを作成
shallow_copied_dict = copy.copy(original_dict)
# 不変オブジェクトの「変更」:フルーツ名と価格を変更
shallow_copied_dict["フルーツ名"] = "orange"
shallow_copied_dict["価格"] = 85
# 「追加」:新しいキーと値を追加
shallow_copied_dict["色"] = "orange"
# 結果の表示
print("元の辞書:", original_dict)
print("浅いコピーの辞書:", shallow_copied_dict)
元の辞書: {'フルーツ名': 'apple', '価格': 100}
浅いコピーの辞書: {'フルーツ名': 'orange', '価格': 85, '色': 'orange'}
深いコピーについて
深いコピーは外見も中身も全て新しく作り直し、完全に独立したコピーを作成します。
ですので、深いコピーを使用した場合、可変オブジェクトと不変オブジェクトのどちらに対して「追加」、「削除」、「変更」などの操作を行なっても、元の辞書には影響を及ぼしません。
実際にコード例を見てみましょう。
深いコピーされた辞書に加えた変更(可変オブジェクトへの追加、不変オブジェクトの変更および新しいキーの追加)が元の辞書に影響を与えないことが確認できます。
# 深いコピーでの可変オブジェクトと不変オブジェクトに対する操作のコード例
# 深いコピーを使用するためにcopyモジュールをインポート
import copy
# 元の辞書を作成(不変オブジェクトと可変オブジェクトを含む)
original_dict = {
"フルーツ名": "apple", # 不変オブジェクト
"価格": 100, # 不変オブジェクト
"色": ["red", "green"] # 可変オブジェクト(リスト)
}
# 深いコピーを作成
deep_copied_dict = copy.deepcopy(original_dict)
# 可変オブジェクト(リスト)に対する「追加」操作
deep_copied_dict["色"].append("yellow")
# 不変オブジェクトに対する「変更」操作
deep_copied_dict["フルーツ名"] = "banana"
deep_copied_dict["価格"] = 120
# 不変オブジェクトに対する「追加」操作
deep_copied_dict["産地"] = "Ecuador"
# 結果の表示
print("元の辞書:", original_dict)
print("深いコピーの辞書:", deep_copied_dict)
元の辞書: {'フルーツ名': 'apple', '価格': 100, '色': ['red', 'green']}
深いコピーの辞書: {'フルーツ名': 'banana', '価格': 120, '色': ['red', 'green', 'yellow'], '産地': 'Ecuador'}
deep_copied_dict = copy.deepcopy(original_dict)
この行でdeepcopy
関数を使って、original_dict
の深いコピーを作成しています。
深いコピーの定義の仕方辞書 = cop.deepcopy(コピーしたい辞書)
コピーする際の注意点


データをコピーする際、特に深いコピーの使用は、一見すると万能のように思えます。
しかし、深いコピーには、見えないコストが伴います。
それは、より多くのメモリ使用と処理時間の増加です。
深いコピーを行うと、元のデータ構造に含まれるすべての要素が新しく作成されます。
これは、データ構造が大きい場合や、多くのネストされたオブジェクトを含む場合に、大量のメモリを消費する可能性があります。
また、全てをコピーする処理には時間がかかります。
考慮すべき点
- メモリの制限:
特に大規模なデータや複雑なデータ構造を扱う場合、深いコピーはメモリ使用量を急激に増加させる可能性があります。
システムのメモリ容量を超えないように注意が必要です。 - パフォーマンス:
処理速度も重要な考慮事項です。
データのコピーに時間がかかりすぎると、アプリケーションのパフォーマンスに悪影響を与える可能性があります。
特にリアルタイムでの応答が求められるアプリケーションでは、深いコピーの使用は慎重に行うべきです。
まとめ
コピーをする際、特にプログラミングの世界では、浅いコピーと深いコピー、そして不変オブジェクトと可変オブジェクトの違いを理解することが非常に重要です。
これらの概念を理解することで、データを扱う際の潜在的な落とし穴を避け、より効率的でバグの少ないプログラムを書くことができるようになります。
今回の記事が、皆様のお役に立てたら幸いです。
コメント