"copy" --- 浅いコピーおよび深いコピー操作
*****************************************

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

======================================================================

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

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

copy.copy(obj)

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

copy.deepcopy(obj[, memo])

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

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

   *obj* と同じ型の新しいオブジェクトを作成し、フィールドを *changes*
   の値で置き換えます。

   Added in version 3.13.

exception copy.Error

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

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

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

* *深いコピー (deep copy)* は新しい複合オブジェクトを作成し、元のオブ
  ジェクトに含まれるオブジェクトを再帰的に *コピー* して挿入します。

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

* 再帰的なオブジェクト (直接または間接に自分自身への参照を含む複合オブ
  ジェクト) は、再帰ループを引き起こすことがあります。

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

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

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

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

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

多くのコレクションでは、対応する "copy()" メソッド ("list.copy()"、
"dict.copy()"、"set.copy()" など) で浅いコピーを作成できます。 また、
リストやバイト配列などのシーケンスでは、全体のスライス ("sequence[:]")
を作成することでも浅いコピーを作れます。 ただし、これらのメソッドやス
ライス操作は、サブクラスのインスタンスをコピーするときに基底型のインス
タンスを作成することがありますが、"copy.copy()" は通常、同じ型のインス
タンスを返します。

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

クラス独自のコピー処理を実装するには、特殊メソッド "__copy__()" と
"__deepcopy__()" を定義できます。

object.__copy__(self)

   浅いコピー操作を実装するために呼び出されます。 追加の引数は渡されま
   せん。

object.__deepcopy__(self, memo)

   深いコピー操作を実装するために呼び出されます。 引数として *memo* 辞
   書が 1 つ渡されます。 "__deepcopy__" の実装内で構成要素の深いコピー
   が必要な場合は、第 1 引数にその構成要素、第 2 引数に *memo* 辞書を
   渡して "deepcopy()" 関数を呼び出す必要があります。 *memo* 辞書は内
   部構造に立ち入らない不透明なオブジェクトとして扱ってください。

"copy.replace()" 関数は "copy()" や "deepcopy()" より制限が多く、
"namedtuple()" で作成した名前付きタプル、"dataclasses"、および
"__replace__()" メソッドを定義するクラスのみをサポートします。

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

   このメソッドは、フィールドを *changes* の値で置き換えた、同じ型の新
   しいオブジェクトを作成する必要があります。

   Added in version 3.13.

参考:

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