2013-03-28 33 views
10

ポインタの概念があるので、C++でコピーコンストラクタ(またはオーバーロードされた代入演算子)を実装するのは簡単です。しかし、私はPythonで浅く深いコピーを実装する方法についてはかなり混乱しています。Python:浅く深いコピーコンストラクタの実装

ライブラリの1つに特別なコマンドがあることは知っていますが、自分で作成したクラスでは機能しません。では、一般的な実装方法は何ですか?

P.S.いくつかの基本的なデータ構造(リンクされたリストやツリー)のプロセスを表示することができます。

編集:ありがとう、彼らは働いた、それは構文の私の間違いだった。 私はこれらの機能を__copy__()__deep_copy()__で上書きすることに非常に興味があります。例えば。どのような種類の情報がデータ構造内にあるのかを知らずに深いコピーを作成するにはどうすればよいですか?

+5

自分でデザインしたクラスでライブラリが動作しないとはどういう意味ですか? 'copy.copy'と' copy.deepcopy'で何が問題になっていますか? –

答えて

22

Python copy moduleは、クラスがコピー動作をカスタマイズできるように、pickle moduleインターフェイスを再利用できます。

カスタムクラスのインスタンスの既定値は、新しい空のクラスを作成し、__class__属性をスワップし、次に浅いコピーの場合はコピーの__dict__を元の値で更新するだけです。ディープコピーは、代わりに__dict__を再帰します。

それ以外の場合は、__getstate__()メソッドを指定して内部状態を返します。これはあなたのクラス__setstate__()が再び受け入れることができる任意の構造にすることができます。

まただけコピー動作を制御するために__copy__()および/または__deepcopy__()方法を指定することができます。これらのメソッドはすべてコピー自体を行うことが期待され、__deepcopy__()メソッドは再帰的なdeepcopy()呼び出しに渡すメモマッピングに渡されます。

例は次のようになります。

from copy import deepcopy 

class Foo(object): 
    def __init__(self, bar): 
     self.bar = bar 
     self.spam = expression + that * generates - ham # calculated 

    def __copy__(self): 
     # self.spam is to be ignored, it is calculated anew for the copy 
     # create a new copy of ourselves *reusing* self.bar 
     return type(self)(self.bar) 

    def __deepcopy__(self, memo): 
     # self.spam is to be ignored, it is calculated anew for the copy 
     # create a new copy of ourselves with a deep copy of self.bar 
     # pass on the memo mapping to recursive calls to copy.deepcopy 
     return type(self)(deepcopy(self.bar, memo)) 

この例では、新しいインスタンスが新たに計算されますようself.spamは、あまりにもコピーされるのを防ぐために、カスタムコピーフックを定義します。

+0

私は最後の解決に非常に興味があります。どのようにタイプを知らなくても、別の値をコピーすることはできますか?私はすべての型のために書くべきですか、それとももっと簡単な解決法がありますか? –

+1

@KudayarPirimbaev:含まれている値を 'copy.deepcopy'再帰呼び出しに委譲します。それは異なるタイプを扱います。 –

+0

ありがとう、私はポイントを理解した –

関連する問題