2012-04-22 30 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 

Tại sao deepcopy chậm hơn 15 lần so với copy?copy.copy vs copy.deepcopy hiệu suất trên tuples

Mỗi hàm phải lặp qua các phần tử của bộ dữ liệu. Trong lần lặp lại đó, copy tạo một tham chiếu khác cho từng phần tử; deepcopy sâu mỗi phần tử.

Nhưng mỗi phần tử là int và việc vẽ sâu một int chỉ cần tạo một tham chiếu khác cho nó. Nói cách khác, hai hàm dường như thực hiện chính xác các bước giống nhau, cùng một số lần.

Đây là xác minh rằng không có trường hợp mới được tạo ra trong quá trình này:

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

Không phải là câu trả lời thực sự, nhưng nghi ngờ: 'deepcopy' cần theo dõi các phần tử đã sao chép để cho phép tham chiếu tuần hoàn, có thể thêm một số phí, đặc biệt trong những trường hợp đơn giản như vậy. – Philipp

+0

Nếu bạn có thể cuộn bản sao của riêng bạn của "deepcopy" nó có thể có giá trị nó. Tôi đã lược tả một số mã thuật toán tiến hóa và nó đã dành rất nhiều thời gian trong bản in sâu. Tôi đã có thể xác định các ràng buộc cần thiết cho thuật toán và viết phiên bản giới hạn của bản thân sâu của tôi mà dẫn đến một tốc độ đáng kể. Số dặm của bạn có thể thay đổi. – Levon

Trả lời

6

Tuples là không thay đổi, nhưng họ có thể chứa các thành phần có thể thay đổi:

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

Lưu ý rằng các tuple không thay đổi : đó là danh sách người làm; tuple vẫn chứa chính xác cùng một danh sách.

deepcopy nên recurse sao chép các yếu tố có thể thay đổi đó. copy chỉ sao chép các tham chiếu đến chúng.

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

Có, nhưng cả hai 'copy' và' deepcopy' cần phải lặp qua các phần tử của bộ dữ liệu. Khi chúng thực hiện, 'copy' tạo một tham chiếu khác cho mỗi' int', trong khi 'deepcopy' sao chép cá thể' int'. Nhưng việc sao chép cá thể 'int' đơn giản trả về một tham chiếu khác cho cùng một cá thể. Có vẻ như hai chức năng nên làm chính xác các bước tương tự. Tôi không thấy làm thế nào kết quả này trong hit hiệu suất 15x. – max

+1

Tôi không nghĩ rằng nó cần thiết để lặp qua bộ dữ liệu để sao chép cạn. Mà không biết rằng nhiều về Python internals, tôi đoán rằng một cuộc gọi memcpy là đủ. –

+3

Bạn nói đúng, không cần phải lặp lại cho 'copy'. Python thậm chí không cần 'memcpy': nó chỉ có thể trả về một tham chiếu khác tới tuple gốc! Tất nhiên, điều đó sẽ không hoạt động đối với 'deepcopy'. – max