它實際上取決於您的班級所需的行爲,決定要重寫的內容(__copy__
或__deepcopy__
)。
一般copy.deepcopy
作品大多正常,它只是複製一切(recursivly),所以你只需要重寫,如果有一些屬性是不得複製(永遠!)。
另一方面,只有當用戶(包括您自己)不希望更改傳播到複製的實例時,才應該定義__copy__
。例如,如果您僅包裝可變類型(如list
)或使用可變類型作爲實現細節。
然後還有一種情況是,要複製的最小屬性集沒有明確定義。在這種情況下,我也會覆蓋__copy__
,但也許會在那裏提高TypeError
,並且可能包含一個(或多個)專用公衆copy
方法。
然而在我看來,arr
算作實現細節,因此我會覆蓋__copy__
:
class T(object):
def __init__(self, x, y):
self.arr = [x, y]
def __copy__(self):
new = self.__class__(*self.arr)
# ... maybe other stuff
return new
只是爲了顯示它按預期工作:
from copy import copy, deepcopy
x = T([2], [3])
y = copy(x)
x.arr is y.arr # False
x.arr[0] is y.arr[0] # True
x.arr[1] is y.arr[1] # True
x = T([2], [3])
y = deepcopy(x)
x.arr is y.arr # False
x.arr[0] is y.arr[0] # False
x.arr[1] is y.arr[1] # False
只是快速的音符關於期望:
用戶一般期望t您可以將實例傳遞給構造函數以創建最小副本(與__copy__
類似或相同)。例如:
lst1 = [1,2,3,4]
lst2 = list(lst1)
lst1 is lst2 # False
一些Python類型具有顯式copy
方法,即(如果存在)應該做相同__copy__
。這將允許在參數明確地傳遞(不過我還沒有看到行動尚未這個):
lst3 = lst1.copy() # python 3.x only (probably)
lst3 is lst1 # False
如果你的類應該被其他人使用你可能需要考慮這些問題,但是如果你只是想讓你的課程與copy.copy
一起工作,然後覆蓋__copy__
。
「深」的概念來自遞歸部分,否則說「深層副本構造一個新的複合對象,然後插入深層副本」將是一個遞歸描述。 –