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

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

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

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

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

copy.copy(x)

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

copy.deepcopy(x[, memo])

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

exception copy.Error

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

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

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

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

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

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

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

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

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

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

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

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

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

クラス独自のコピー実装を定義するために、特殊メソッド "__copy__()" およ
び "__deepcopy__()" を定義することができます。前者は浅いコピー操作を実
装するために使われます; 追加の引数はありません。後者は深いコピー操作を
実現するために呼び出されます; この関数には単一の引数として "memo" 辞書
が渡されます。 "__deepcopy__()" の実装で、内容のオブジェクトに対して深
いコピーを生成する必要がある場合、 "deepcopy()" を呼び出し、最初の引数
にそのオブジェクトを、メモ辞書を二つ目の引数に与えなければなりません。
メモ辞書は中が見えないオブジェクトとして扱うべきです。

参考:

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