【Python】オブジェクトをコピーするcopyの使い方と注意点を解説

目次から探す

コピーの注意点

Pythonでオブジェクトをコピーする際には、いくつかの注意点があります。

この章では、参照渡しと値渡しの違い、ミュータブルとイミュータブルなオブジェクトの違い、コピー時のオブジェクトIDの変化、カスタムオブジェクトのコピーについて解説します。

参照渡しと値渡しの違い

Pythonでは、オブジェクトのコピーには参照渡しと値渡しの2種類があります。

参照渡し

オブジェクトへの参照(アドレス)が渡される。

オリジナルのオブジェクトとコピーされたオブジェクトが同じメモリ上のデータを参照しているため、片方を変更するともう片方も変更される。

値渡し

オブジェクトの値が渡される。

オリジナルのオブジェクトとコピーされたオブジェクトが別々のメモリ上のデータを参照しているため、片方を変更してももう片方は変更されない。

ミュータブルとイミュータブルなオブジェクトの違い

Pythonのオブジェクトには、ミュータブル(変更可能)とイミュータブル(変更不可)の2種類があります。

ミュータブル

リスト、辞書、集合など、要素の追加や削除、変更が可能なオブジェクト。

イミュータブル

数値、文字列、タプルなど、要素の追加や削除、変更ができないオブジェクト。

ミュータブルなオブジェクトをコピーする際には、参照渡しや浅いコピーでは意図しない動作が発生することがあるため、深いコピーを使用することが推奨されます。

コピー時のオブジェクトIDの変化

Pythonでは、オブジェクトのIDを «id()» 関数で取得できます。

オブジェクトをコピーした際に、オブジェクトIDが変化するかどうかで、参照渡しと値渡しを判断することができます。


import copy
original_list = [1, 2, 3]
shallow_copied_list = copy.copy(original_list)
deep_copied_list = copy.deepcopy(original_list)
print("オリジナルのID:", id(original_list))
print("浅いコピーのID:", id(shallow_copied_list))
print("深いコピーのID:", id(deep_copied_list))
オリジナルのID: 1692542043008
浅いコピーのID: 1692542042816
深いコピーのID: 1692542042752

この例では、オリジナルのリストと浅いコピー、深いコピーのリストのIDが異なることがわかります。

これにより、参照渡しではなく値渡しでコピーされていることが確認できます。

カスタムオブジェクトのコピー

Pythonで定義したカスタムオブジェクトも、 «copy.copy()» や «copy.deepcopy()» を使ってコピーすることができます。

ただし、カスタムオブジェクトの属性にミュータブルなオブジェクトが含まれている場合は、深いコピーを使用することが推奨されます。


import copy
class CustomObject:
    def __init__(self, name, data):
        self.name = name
        self.data = data
original_obj = CustomObject("オリジナル", [1, 2, 3])
shallow_copied_obj = copy.copy(original_obj)
deep_copied_obj = copy.deepcopy(original_obj)
print("オリジナルのID:", id(original_obj))
print("浅いコピーのID:", id(shallow_copied_obj))
print("深いコピーのID:", id(deep_copied_obj))
オリジナルのID: 1692542056528
浅いコピーのID: 1692542099856
深いコピーのID: 1692542102416

この例でも、オリジナルのオブジェクトと浅いコピー、深いコピーのオブジェクトのIDが異なることがわかります。

これにより、参照渡しではなく値渡しでコピーされていることが確認できます。

1 2
この記事のページ一覧
  1. 現在のページ
目次から探す