2017-10-12 16 views
7

Giả sử tôi tạo python lists theo hai cách.
Tại sao danh sách có cùng dữ liệu có kích thước khác nhau?

Trong trường hợp đầu tiên tôi sử dụng phân đơn giản:

my_list = [] 
print(my_list, '->', my_list.__sizeof__()) 
my_list = [1] 
print(my_list, '->', my_list.__sizeof__()) 
my_list = [1, 1] 
print(my_list, '->', my_list.__sizeof__()) 

Trong trường hợp thứ hai tôi sử dụng append() phương pháp trên danh sách:

my_list = [] 
print(my_list, '->', my_list.__sizeof__()) 
my_list.append(1) 
print(my_list, '->', my_list.__sizeof__()) 
my_list.append(1) 
print(my_list, '->', my_list.__sizeof__()) 

Nhưng tôi nhận được bất ngờ (cho tôi) đầu ra:

=== WITH ASSIGNMENT === 
([], '->', 40) 
([1], '->', 48) 
([1, 1], '->', 56) 
=== WITH APPEND === 
([], '->', 40) 
([1], '->', 72) 
([1, 1], '->', 72) 

Điều gì xảy ra bên trong với bộ nhớ Python manag ement? Tại sao các danh sách 'cùng' có kích thước khác nhau?

+2

Tôi đoán vì khi bạn tạo danh sách dưới dạng Python nghĩa đen chỉ định kích thước cụ thể cần thiết, trong khi khi bạn thêm vào, nó sẽ mở rộng nhiều hơn mức được yêu cầu trên giả định rằng bạn sẽ không nối thêm một lần nữa. – jonrsharpe

+0

[nội bộ của truy cập danh sách python và định lại thời gian chạy lại] (https://stackoverflow.com/questions/5932328/internals-of-python-list-access-and-resizing-runtimes) – anuragal

Trả lời

14

Khi bạn chắp thêm vào danh sách, bộ nhớ được phân bổ quá mức vào danh sách cho hiệu suất lý do sao cho nhiều phụ thêm sẽ không yêu cầu phân bổ lại bộ nhớ tương ứng cho danh sách sẽ làm chậm hiệu suất tổng thể trong trường hợp lặp lại .

nguồn

Các CPython mô tả rõ ràng hành vi này trong một comment:

/* This over-allocates proportional to the list size, making room 
* for additional growth. The over-allocation is mild, but is 
* enough to give linear-time amortized behavior over a long 
* sequence of appends() in the presence of a poorly-performing 
* system realloc(). 
* The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ... 
* Note: new_allocated won't overflow because the largest possible value 
*  is PY_SSIZE_T_MAX * (9/8) + 6 which always fits in a size_t. 
*/ 

Trong trường hợp khác, danh sách này được xây dựng từ một chữ, và kích thước của danh sách phản ánh kích thước của hộp đựng và tham chiếu đến từng đối tượng chứa.

Hành vi phân bổ chính xác có thể thay đổi với các triển khai Python khác (xem list.append triển khai cho JythonPyPy) và không phân phối quá mức.

Các vấn đề liên quan