この記事では、Pythonでオブジェクトのコピーとディープコピーについて詳しく解説します。具体的なコード例とその解説、応用例を含めています。
はじめに
Pythonにおいてオブジェクトのコピーは、多くの場面で避けては通れないテーマです。しかし、単純に`=(代入)`を使用すると、オブジェクトそのものではなく参照がコピーされるため、思わぬバグを引き起こす可能性があります。
浅いコピー(Shallow Copy)とは
Pythonにおいて、一次元のリストや辞書などの単純なオブジェクトは、`copy` モジュールの `copy()` 関数またはスライス記法などでコピーすることができます。
浅いコピーの基本的な方法
最も簡単な例として、リストのコピーを考えます。
import copy
original_list = [1, 2, 3]
copied_list = copy.copy(original_list)
# または
copied_list = original_list[:]
print(copied_list) # 出力:[1, 2, 3]
このようにして作成した `copied_list` は、`original_list` の浅いコピーです。これは元のリスト内のオブジェクト自体は参照されるため、元のリストが持つサブオブジェクト(ネストされたオブジェクト)が変更されると、コピーも影響を受けます。
深いコピー(Deep Copy)とは
`copy` モジュールの `deepcopy()` 関数を使うことで、ネストされたオブジェクトまで新しいオブジェクトとしてコピーが可能です。
深いコピーの基本的な方法
ネストされたリストをコピーする例です。
import copy
original_list = [1, [2, 3], 4]
deep_copied_list = copy.deepcopy(original_list)
print(deep_copied_list) # 出力:[1, [2, 3], 4]
応用例
オブジェクトのカスタムコピー
`__copy__()` と `__deepcopy__()` メソッドをクラス内に定義することで、カスタムなコピー動作を実現することができます。
import copy
class MyClass:
def __init__(self, value):
self.value = value
def __copy__(self):
return MyClass(self.value * 2)
def __deepcopy__(self, memo):
return MyClass(self.value * 3)
obj = MyClass(10)
shallow_copied_obj = copy.copy(obj)
deep_copied_obj = copy.deepcopy(obj)
print(shallow_copied_obj.value) # 出力:20
print(deep_copied_obj.value) # 出力:30
不変オブジェクトとコピー
文字列やタプルなどの不変オブジェクトの場合、通常のコピーと深いコピーは同じ結果となります。
immutable_obj = (1, 2, 3)
copied_obj = copy.copy(immutable_obj)
deep_copied_obj = copy.deepcopy(immutable_obj)
print(copied_obj is immutable_obj) # 出力:True
print(deep_copied_obj is immutable_obj) # 出力:True
複数の参照を持つオブジェクトのコピー
1つのオブジェクトが複数の場所で参照されている場合、深いコピーはその関連も保持します。
lst1 = [1, 2, 3]
lst2 = [lst1, 4, 5]
deep_copied_lst2 = copy.deepcopy(lst2)
deep_copied_lst2[0][0] = 'changed'
print(deep_copied_lst2) # 出力:[['changed', 2, 3], 4, 5]
print(lst2) # 出力:[[1, 2, 3], 4, 5]
まとめ
Pythonでのオブジェクトのコピーには注意が必要であり、状況に応じて浅いコピーと深いコピーを選択する必要が
あります。また、カスタムオブジェクトで独自のコピー動作を実装することも可能です。
コメント