2012-05-17 51 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的相應屬性的值來設置自己的每個屬性,但這會非常煩人,因爲我的類具有許多屬性。或者我可以簡單地使用do:

b = copy.deepcopy(a) 

......但我寧願不,如果這是可能的。我也希望避免重寫__new__

python中是否真的沒有像樣的方法來創建複製構造函數?

+3

爲什麼不你想使用b = copy.deepcopy(a)?我的意思是,如果它可以工作,並且不需要再寫入比b = Foo(a)更多的行.... – DGH

+0

那麼,我想我的手指仍然交叉,複製構造函數是可行的。坦率地說,爲什麼不呢?這不像是一個非常不尋常的要求。人們會認爲所有面向對象的語言都會有這個特性。 – carmenism

+1

爲什麼它不是一個功能?因爲它只是語法糖,用不同的方式來表達完全相同的東西。只要功能存在只用一行非常簡單的代碼就可以進行深層複製,爲什麼它是否是「構造函數」呢? – DGH

回答

16

我認爲這是實現它的最pythonic方式 - 複製工廠方法。

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__源對象上的所有屬性,然後setattr()您關注self的人。但是,這是解決問題的好方法,一點也不清楚。不是非常Pythonic,等等。

+0

我也想知道,但它確實不太Pythonic。不管怎麼說,還是要謝謝你。 – carmenism

0

這樣做的一個好方法是創建實例名稱空間的頂級副本。

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()