2012-04-22 45 views
5
%python -m timeit -s "import copy" "x = (1, 2, 3)" "copy.deepcopy(x)" 
100000 loops, best of 3: 10.1 usec per loop 

%python -m timeit -s "import copy" "x = (1, 2, 3)" "copy.copy(x)" 
1000000 loops, best of 3: 0.609 usec per loop 

爲什麼deepcopycopy慢15倍?copy.copy vs copy.deepcopy元組上的性能

每個函數都必須迭代元組中的元素。在該迭代期間,copy爲每個元素創建另一個引用; deepcopy深度覆蓋每個元素。

但是每個元素都是int,而深拷貝int只是創建另一個引用。換句話說,這兩個功能似乎執行完全相同的步驟,相同的次數。

這裏有沒有新的實例在過程中創建的驗證:

ActivePython 3.2.1.2 (ActiveState Software Inc.) based on 
Python 3.2.1 (default, Jul 18 2011, 14:31:09) [MSC v.1500 64 bit (AMD64)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> x = (1,2,3) 
>>> import copy 
>>> y = copy.copy(x) 
>>> z = copy.deepcopy(x) 
>>> x is y 
True 
>>> x is z 
True 
>>> x[1] is z[1] 
True 
+1

不是一個真正的答案,但懷疑:'deepcopy'需要保持的元素它已經被複制到允許循環引用,這可能會增加一些開銷,尤其是在這種簡單的情況下軌道。 – Philipp 2012-04-22 19:23:13

+0

如果您可以推出自己的「deepcopy」副本,這可能是值得的。我正在分析一些演化算法代碼,它在深度拷貝上花費了大量時間。我能夠確定算法所需的約束條件,並編寫自己的限制版本的deepcopy,從而大大加快了速度。你的旅費可能會改變。 – Levon 2012-04-22 19:27:42

回答

6

元組是不可改變的,但可以包含可變元素:

>>> a = (1, 2, []) 
>>> a[2].append(1000) 
>>> a 
(1, 2, [1000]) 

注意,元組沒有變化:這是一個名單,該元組仍然包含完全相同的列表。

deepcopy應該遞歸複製這些可變元素。 copy只是複製對它們的引用。

>>> from copy import copy, deepcopy 

>>> a = (1, 2, []) 
>>> c = copy(a) 
>>> d = deepcopy(a) 

>>> a[2].append(1000) 

>>> c 
(1, 2, [1000]) 
>>> d 
(1, 2, []) 
+1

是的,但'copy'和'deepcopy'都需要迭代元組元素。當他們這樣做時,'copy'爲每個'int'創建另一個引用,而'deepcopy'複製'int'實例。但是複製'int'實例只是返回對同一個實例的另一個引用。似乎這兩個功能應該完全相同的步驟。我不明白這是如何導致15倍的性能下降。 – max 2012-04-22 19:16:18

+1

我不認爲有必要遍歷元組進行淺拷貝。在不瞭解Python內部知識的情況下,我猜想memcpy調用應該足夠了。 – 2012-04-22 19:19:22

+3

你是對的,不需要迭代'copy'。 Python甚至不需要'memcpy':它只能返回對原始元組的另一個引用!當然,這對於'deepcopy'不起作用。 – max 2012-04-22 19:26:30