2012-04-20 77 views
6

我的課程表示各種系統的狀態。每個實例都有兩個屬性:一個是在同一個系統的所有狀態之間共享的容器,另一個是每個實例都獨有的容器。copy vs deepcopy:語義

狀態的副本應該重用「共享」屬性,但創建「唯一」屬性的深層副本。這實際上是唯一有意義的複製語義(狀態的副本是同一個系統的狀態是很自然的)。

我想爲閱讀和維護代碼的人創造最少的驚喜。我應該爲我的目的覆蓋__deepcopy____copy__嗎?

+0

'__deepcopy__'如果你正在服用一個民意調查... – 2012-04-20 21:42:29

+0

嗯,我希望能夠達成一致意見:)而且在每個人都有機會看到每個人的迴應後,情況可能仍然存在。 – max 2012-04-20 22:31:56

回答

3

是否真的有必要使用複製模塊來複制此類的實例?我會爭辯說,而不是重寫__copy____deepcopy__您應該爲您的類創建一個copy方法,該方法使用您定義的複製語義返回一個新對象。

如果出於某種一致性原因您確實需要使用複製模塊,那麼在我看來__deepcopy__更合適。如果它是所有實例共享其中一個容器的類的已定義行爲,那麼假設__deepcopy__的實現將遵守這一點是合理的。

+0

我很好,沒有使用'copy'模塊。但是如果我定義了一個'copy'方法,讀者是不是會認爲它是一個像dict或set這樣的淺拷貝? – max 2012-04-20 22:09:03

+0

@max,你的類是「dict」還是「set」的子類?如果不是,那麼讀者不應該假設你的課程的'copy'方法應該模仿從內置類型的'copy'。 – 2012-04-20 22:24:51

+0

@max:我認爲你總會對一些讀者感到驚訝,因爲你的意圖語義既不是完全淺的,也不是完全深刻的。但是在定義自定義複製語義的所有可能的地方,我認爲一個類的「複製」方法是最有可能被定製的方法。如果完全淺層和完全深層的語義真的*對你的課堂沒有意義,那麼爲什麼不重寫他們呢? (你可以使'__copy__'和'__deepcopy__'調用類的'copy'。) – 2012-04-20 22:26:36

0

這是與這種類似情況嗎?

import copy 

class Foo(object): 
    shared = [[]] 
    def __init__(self): 
     self.perinstance = [[]] 

如果是這樣,那麼看來你並不需要定義__copy____deepcopy__,因爲copy.deepcopy股類屬性的默認行爲,並deepcopies實例屬性:

x = Foo() 
z = copy.deepcopy(x) 
assert id(z.shared) == id(x.shared) 
assert id(z.shared[0]) == id(x.shared[0]) 
assert id(z.perinstance) != id(x.perinstance) 
assert id(z.perinstance[0]) != id(x.perinstance[0]) 
+0

不幸的是,我的共享屬性是一個實例屬性。我的解釋不準確。 「共享」屬性可以在不同實例之間有所不同,但前提是它們對應於不同的系統。複製語義(如您所期望的)從同一個系統創建一個狀態的副本,因此它具有相同的共享屬性值。我正在更新這個問題來澄清這一點。 – max 2012-04-20 22:11:59