# `copy` --- 浅いコピーおよび深いコピー操作

ソースコード: Lib/copy.py

Python において代入文はオブジェクトをコピーしません。代入はターゲットとオブジェクトの間に束縛を作ります。ミュータブルなコレクションまたはミュータブルなアイテムを含むコレクションについては、元のオブジェクトを変更せずにコピーを変更できるように、コピーが必要になることが時々あります。このモジュールは、汎用的な浅い (shallow) コピーと深い (deep) コピーの操作 (以下で説明されます) を提供します。

以下にインターフェースをまとめます:

copy.copy(obj)

  obj の浅い (shallow) コピーを返します。

copy.deepcopy(obj[, memo])

  obj の深い (deep) コピーを返します。

copy.replace(obj, /, **changes)

  Creates a new object of the same type as obj, replacing fields with values from changes.

  Added in version 3.13.

exception copy.Error

  モジュール特有のエラーを送出します。

浅い (shallow) コピーと深い (deep) コピーの違いが関係するのは、複合オブジェクト (リストやクラスインスタンスのような他のオブジェクトを含むオブジェクト) だけです:

- 浅いコピー (shallow copy) は新たな複合オブジェクトを作成し、その後 (可能な限り) 元のオブジェクト中に見つかったオブジェクトに対する 参照 を挿入します。

- 深いコピー (deep copy) は新たな複合オブジェクトを作成し、その後元のオブジェクト中に見つかったオブジェクトの コピー を挿入します。

深いコピー操作には、しばしば浅いコピー操作の時には存在しない 2 つの問題がついてまわります:

- 再帰的なオブジェクト (直接、間接に関わらず、自分自身に対する参照を持つ複合オブジェクト) は再帰ループを引き起こします。

- 深いコピーは何もかもコピーしてしまうため、例えば複数のコピー間で共有するつもりだったデータも余分にコピーしてしまいます。

`deepcopy()` 関数では、これらの問題を以下のようにして回避しています:

- 現時点でのコピー過程ですでにコピーされたオブジェクトの `memo` 辞書を保持する。

- ユーザ定義のクラスでコピー操作やコピーされる内容の集合を上書きできるようにする。

このモジュールでは、モジュール、メソッド、スタックトレース、スタックフレーム、ファイル、ソケット、ウィンドウ、その他これらに類似の型をコピーしません。このモジュールでは元のオブジェクトを変更せずに返すことで関数とクラスを (浅くまたは深く)「コピー」します。これは `pickle` モジュールでの扱われかたと同じです。

辞書型の浅いコピーは `dict.copy()` で、リストの浅いコピーはリスト全体を指すスライス (例えば `copied_list = original_list[:]`) でできます。

クラスは、コピーを制御するために pickle の制御に使用するのと同じインターフェースを使用することができます。これらのメソッドについての情報はモジュール `pickle` の説明を参照してください。実際、 `copy` モジュールは、 `copyreg` モジュールによって登録された pickle 関数を使用します。

In order for a class to define its own copy implementation, it can define special methods `__copy__()` and `__deepcopy__()`.

object.__copy__(self)

  Called to implement the shallow copy operation; no additional arguments are passed.

object.__deepcopy__(self, memo)

  Called to implement the deep copy operation; it is passed one argument, the memo dictionary. If the `__deepcopy__` implementation needs to make a deep copy of a component, it should call the `deepcopy()` function with the component as first argument and the memo dictionary as second argument. The memo dictionary should be treated as an opaque object.

Function `copy.replace()` is more limited than `copy()` and `deepcopy()`, and only supports named tuples created by `namedtuple()`, `dataclasses`, and other classes which define method `__replace__()`.

object.__replace__(self, /, **changes)

  This method should create a new object of the same type, replacing fields with values from changes.

  Added in version 3.13.

参考

`pickle` モジュール

  オブジェクト状態の取得と復元をサポートするために使われる特殊メソッドについて議論されています。