2012-05-17 26 views
8

私はこれに非常に似た質問をしていますが、正確にはそうではありません。pythonでコピーコンストラクタをうまく作る方法はありますか?

私のクラスのインスタンスであればコピーされる、私のクラスのコンストラクタのオプションの引数が必要です。例えば、何かのように(私が知っているこのコードは動作しません!):私はこれにはいくつかの実用的なソリューションがあります知っている

class Foo(object): 
    def __init__(self, foo=None): 
     self.x = None 
     self.y = None 
     self.z = None 

     if foo is not None and isinstance(foo, Foo): 
      self = copy.deepcopy(foo) 

a = Foo() 
a.x = 1 
a.y = 2 
a.z = 3 

b = Foo(a) 
print b.x 
print b.y 
print b.z 

を。私はfooの対応する属性の値に応じてselfの各属性を設定できますが、クラスには多くの属性が多数含まれているため、これは本当に面倒です。または、私は単純にdoを使用することができます:

b = copy.deepcopy(a) 

...しかし、私はむしろそれが可能な場合はしたいと思います。また、__new__を上書きしないようにしたいと考えています。

実際にコピーコンストラクタを作成するには、Pythonでまともな方法はありませんか?

+3

WHYありませんあなたはb = copy.deepcopy(a)を使いたいですか?私はそれがうまくいくならば、b = Foo(a)よりも書くのにそれ以上の行はありません.... – DGH

+0

まあ、私はコピーコンストラクタが実行可能であると私の指がまだ交差していると思います。そして、率直に言って、どうしてそんなの?それは本当に珍しい要求ではないようです。すべてのオブジェクト指向言語にこの機能があると考えられます。 – carmenism

+1

なぜそれは機能ではありませんか?それはちょうど統語的な砂糖なので、まったく同じことを言う別の方法です。 1つの非常に単純なコード行で深いコピーを作成する機能が存在する限り、それが「コンストラクタ」であるかどうかはなぜ重要ですか? – DGH

答えて

16

これは、コピーファクトリメソッドである、これを行うための最も非凡な方法だと思います。

import copy 

class Foo(object): 
    def __init__(self): 
     self.x = None 
     self.y = None 
     self.z = None 
    def copy(self): 
     return copy.deepcopy(self) 

a = Foo() 
a.x = 1 
a.y = 2 
a.z = 3 

b = a.copy() 
print b.x 
print b.y 
print b.z 

これは、Python基本型(例:dict.copy)でかなり一般的です。それはコピーコンストラクタではありませんが、私はそれが非常にpythonicのコンセプトだとは思わない!

+0

それは私の質問で言及することを忘れた別のアイデアでした。私はこれ以上b = copy.deepcopy(a)以上が好きです。ありがとうございました! – carmenism

0

それはそれであなただけ__init__に渡されたソースオブジェクトのすべての属性を反復処理し、次にあなたがselfに気にsetattr()のものができ、可能です。しかし、これが問題を解決する良い方法であることはまったく明らかではありません。非常にPythonic、およびすべて。

+0

私はそれについても疑問に思っていましたが、確かに非常にPythonicに見えません。とにかくありがとう。 – carmenism

0

これを実行する良い方法の1つは、インスタンスの名前空間の最上位コピーを作成することです。

class Tst: 
    def __init__(self, somearg): 
     if isinstance(somearg, self.__class__): 
      self.__dict__ = somearg.__dict__.copy() 
     else: 
      self.var = somearg 
    def echo(self): 
     print(self.var) 

a = Tst(123) 
b = Tst(456) 
a.echo()  # gives 123 
b.echo()  # gives 456 
c = Tst(a) 
c.echo()  # gives 123 
c.var is a.var # gives False -> different objects 

しかし、あなたのクラスのお得な情報__slots__であれば、その場合には__dict__がないかもしれないので、あなたはより中立的属性取得メカニズムに依存する必要があるため、注意が必要、などgetattr()

関連する問題