この記事では、Pythonでのコレクション型のコピーとディープコピーについて深く探ります。コレクション型とは、リストやディクショナリ、タプルなどのデータを格納するためのデータ型です。単純なコピー(Shallow Copy)とディープコピー(Deep Copy)の違い、それぞれの使いどころとリスク、さらには具体的な実践例についても詳しく解説します。
シャローコピーとディープコピーの基本
Pythonには、コレクション型のデータをコピーするためにいくつかの方法があります。これらは一見似ているように思えるかもしれませんが、シャローコピー(単純なコピー)とディープコピー(深いコピー)は根本的に異なります。
シャローコピーの特性
シャローコピーは、オリジナルのオブジェクトと同じ属性を持つ新しいオブジェクトを生成しますが、その中の要素は参照としてコピーされます。この特性が何を意味するかというと、ネストされたコレクション(例えば、リスト内にリストがある場合)において、内部のリストが変更されると、コピーも影響を受けるということです。
# シャローコピーの例
original_list = [[1, 2, 3], [4, 5, 6]]
shallow_copy = original_list.copy() # copyメソッドでシャローコピー
# 内部リストを変更
original_list[0][0] = 99
# シャローコピーも影響を受ける
print(shallow_copy) # 出力: [[99, 2, 3], [4, 5, 6]]
ディープコピーの特性
一方で、ディープコピーはオリジナルのオブジェクトだけでなく、その中の全てのオブジェクトも再帰的にコピーします。これにより、オリジナルのオブジェクトが持つネストされたコレクションも独立したコピーが生成されます。
import copy
# ディープコピーの例
original_list = [[1, 2, 3], [4, 5, 6]]
deep_copy = copy.deepcopy(original_list) # deepcopyメソッドでディープコピー
# 内部リストを変更
original_list[0][0] = 99
# ディープコピーは影響を受けない
print(deep_copy) # 出力: [[1, 2, 3], [4, 5, 6]]
実践例とその解説
設定値のテンプレート
シャローコピーが役立つ一例として、ある設定値をテンプレートとして使いまわす場合があります。
settings_template = {'user': 'default', 'values': [1, 2, 3]}
user_settings = settings_template.copy()
# 個々の設定を変更
user_settings['user'] = 'John'
user_settings['values'][0] = 99
このようにして、`settings_template` を各ユーザーにカスタマイズできます。
状態の保存と復元
ディープコピーは、オブジェクトの状態を保存して後で復元する場合などに有用です。
import copy
game_state = {'player_pos': [2, 3], 'inventory': ['sword', 'shield']}
saved_state = copy.deepcopy(game_state)
# ゲームの状態を変更
game_state['player_pos'][0] = 4
# 状態を復元
game_state = copy.deepcopy(saved_state)
ネストされたリストのフィルタリング
ディープコピーを用いると、ネストされたリストから特定の条件に一致する要素だけを新しいリストにコピーするような処理も容易になります。
import copy
nested_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
filtered_list = copy.deepcopy(nested_list)
for inner_list in filtered_list:
for i in reversed(range(len(inner_list))):
if inner_list[i] % 2 == 0:
del inner_list[i]
まとめ
この記事では、Pythonのシャローコピーとディープコピーについて、その特性と実践例を交えて詳細に解説しました。適切な場面でこれらの概念を利用することで、より効率的かつ安全なコードを書くことができます。具体的なケースに応じて、シャローコピーとディープコピーを使い分けるスキルは、プログラミングにおいて非常に有用です。
コメント