2016-10-29 15 views
21

tôi có một danh sách my_list (danh sách có chứa chuỗi utf8):Tại sao là một danh sách được sắp xếp lớn hơn một danh sách không được phân loại

>>> len(my_list) 
8777 
>>> getsizeof(my_list)      # <-- note the size 
77848 

Đối với một số lý do, một danh sách sắp xếp (my_sorted_list = sorted(my_list)) sử dụng nhiều bộ nhớ hơn:

>>> len(my_sorted_list) 
8777 
>>> getsizeof(my_sorted_list)    # <-- note the size 
79104 

Tại sao sorted trả về danh sách chiếm nhiều không gian hơn bộ nhớ so với danh sách chưa được phân loại ban đầu?

+1

Vì [@ Jim's answer] (http://stackoverflow.com/a/40317620/3124746) chỉ ra rằng 'sắp xếp' tạo danh sách mới bạn có thể theo dõi câu chuyện với [câu hỏi gần đây của tôi (danh sách() sử dụng nhiều bộ nhớ hơn list comprehension)] (http://stackoverflow.com/questions/40018398/list-uses-more-memory-than-list-comprehension) nó sẽ cung cấp cho bạn một số thông tin chi tiết về python. –

+1

@vishes_shell Hoặc cũng https://stackoverflow.com/questions/7247298/size-of-list-in-memory (hỏi năm 2011) – jcuenod

+1

Tôi thực sự thích các biểu đồ trong câu trả lời cho câu hỏi của bạn @vishes_shell :-). Vấn đề duy nhất tôi thấy với những câu hỏi và câu trả lời này là họ có thể * đột nhiên * trở nên lỗi thời tại một số điểm bởi vì chúng tôi đang xử lý một chi tiết thực hiện: ( –

Trả lời

18

Ignacio points out, điều này là do Python phân bổ bộ nhớ nhiều hơn một chút so với yêu cầu. Việc này được thực hiện để thực hiện O(1).appends trên danh sách.

sortedcreates a new list ngoài chuỗi được cung cấp, sorts it in place và trả lại. Để tạo danh sách mới, Python extends an empty sized list with the one passed; dẫn đến việc phân bổ quá mức được quan sát (xảy ra sau khi gọi list_resize). Bạn có thể chứng thực một thực tế rằng phân loại không phải là thủ phạm bằng cách sử dụng list.sort; thuật toán tương tự được sử dụng mà không có danh sách mới được tạo (hoặc, được biết, đó là được thực hiện tại chỗ). Các kích thước ở đó, tất nhiên, không khác nhau.

Điều đáng chú ý là sự khác biệt này chủ yếu là mặt khi:

Như vậy, với một danh sách-comp:

l = [i for i in range(10)] 

getsizeof(l)   # 192 
getsizeof(sorted(l)) # 200 

Hoặc một danh sách đen:

l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

getsizeof(l)   # 144 
getsizeof(sorted(l)) # 200 

kích thước nhỏ hơn (nhiều hơn thế với việc sử dụng các chữ).

Khi tạo thông qua list, bộ nhớ luôn được phân phối quá mức; Python knows the sizes và có cản thay đổi tương lai bằng quá phân bổ một chút dựa trên kích thước:

l = list(range(10)) 

getsizeof(l)   # 200 
getsizeof(sorted(l)) # 200 

Vì vậy, bạn không nhận được sự khác biệt quan sát được trong các kích thước của danh sách (s).


Là một lưu ý cuối cùng, tôi phải chỉ ra rằng đây là một hành vi cụ thể thi C của Python tức là CPython.Đó là một chi tiết về cách ngôn ngữ được thực hiện và như vậy, bạn không nên phụ thuộc vào nó trong bất kỳ cách thức lập dị.

Jython, IronPython, PyPy và bất kỳ triển khai nào khác có thể/có thể không có hành vi tương tự.

13

list resize operation tổng quát để phân bổ phụ thêm vào danh sách so với bắt đầu với danh sách được trình biên dịch giải thích.

+1

Cảm ơn bạn đã liên kết tới mã của Python! Thật tuyệt vời ... Tôi đã chấp nhận nhưng chi tiết trong câu trả lời của @ Jim đã thắng tôi. – jcuenod

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