Bộ và dicts được tối ưu hóa cho các trường hợp sử dụng khác nhau. Việc sử dụng chính của một bộ là thử nghiệm thành viên nhanh, đó là thuyết bất khả tri. Đối với các thiết bị, chi phí tra cứu là hoạt động quan trọng nhất và chìa khóa có nhiều khả năng có mặt. Với các tập hợp, sự hiện diện hoặc vắng mặt của một phần tử không được biết trước và do đó, việc thực hiện tập hợp cần tối ưu hóa cho cả trường hợp tìm thấy và không tìm thấy. Ngoài ra, một số tối ưu hóa cho các hoạt động tập hợp phổ biến như liên kết và giao cắt làm cho việc giữ lại trật tự thiết lập mà không làm giảm hiệu suất.
Mặc dù cả hai cấu trúc dữ liệu đều dựa trên hàm băm, nhưng đó là một quan niệm sai lầm phổ biến rằng các tập hợp chỉ được triển khai dưới dạng các giá trị null. Ngay cả trước khi triển khai chính tả nhỏ gọn trong CPython 3.6, các triển khai tập hợp và chính tả đã khác nhau đáng kể, với việc sử dụng lại ít mã. Ví dụ, các dicts sử dụng thăm dò ngẫu nhiên, nhưng các bộ sử dụng kết hợp giữa thăm dò tuyến tính và địa chỉ mở, để cải thiện cục bộ bộ đệm. Đầu dò tuyến tính ban đầu ( 9 bước mặc định trong CPython) sẽ kiểm tra một loạt các cặp khóa / băm liền kề, cải thiện hiệu suất bằng cách giảm chi phí xử lý va chạm băm - truy cập bộ nhớ liên tiếp rẻ hơn so với các đầu dò phân tán.
dictobject.c
- chủ , v3.5.9
setobject.c
- chủ , v3.5.9
- vấn đề18771 - thay đổi để giảm chi phí va chạm băm cho các đối tượng thiết lập trong Python 3.4.
Nó sẽ là tốt về mặt lý thuyết để thay đổi thực hiện bộ CPython cho bạn trở thành tương tự như dict nhỏ gọn, nhưng trong thực tế có những nhược điểm, và các nhà phát triển cốt lõi đáng chú ý được chứ không phải thực hiện một sự thay đổi đó.
Bộ vẫn không có thứ tự. (Tại sao? Các mô hình sử dụng là khác nhau. Ngoài ra, việc thực hiện khác nhau.)
- Guido van Rossum
Các bộ sử dụng một thuật toán khác không thể sửa đổi để giữ lại thứ tự chèn. Các thao tác cài đặt sẽ mất tính linh hoạt và tối ưu hóa nếu yêu cầu đặt hàng. Tập toán học được định nghĩa theo các tập hợp không có thứ tự. Nói tóm lại, đặt hàng không phải là trong tương lai trước mắt.
- Raymond Hettinger
Một cuộc thảo luận chi tiết về việc có nên thu gọn các bộ cho 3.7 hay không và câu trả lời về lý do tại sao nó được quyết định chống lại, có thể được tìm thấy trong danh sách gửi thư của python-dev.
Tóm lại, những điểm chính là các kiểu sử dụng khác nhau (các ký tự đặt hàng chèn như ** kwargs là hữu ích , ít hơn cho các bộ), tiết kiệm không gian cho các bộ nén là ít quan trọng hơn (vì chỉ có mảng khóa và hàm băm tăng cường, trái ngược với các khóa, băm và giá trị) và tối ưu hóa thăm dò tuyến tính đã nói ở trên không tương thích với việc triển khai nhỏ gọn.
Tôi sẽ sao chép bài của Raymond dưới đây bao gồm những điểm quan trọng nhất.
Vào ngày 14 tháng 9 năm 2016, lúc 3:50 PM, Eric Snow đã viết:
Sau đó, tôi sẽ làm tương tự với các bộ.
Trừ khi tôi hiểu lầm, Raymond phản đối việc thực hiện một thay đổi tương tự để thiết lập.
Đúng rồi. Dưới đây là một vài suy nghĩ về chủ đề này trước khi mọi người bắt đầu chạy hoang dã.
Đối với lệnh nhỏ gọn, tiết kiệm không gian là một chiến thắng ròng với không gian bổ sung được sử dụng bởi các chỉ số và tổng thể cho các mảng khóa / giá trị / hàm băm được bù đắp nhiều hơn bởi mật độ cải thiện của mảng khóa / giá trị / hàm băm. Tuy nhiên, đối với các bộ, mạng ít thuận lợi hơn nhiều vì chúng ta vẫn cần các chỉ số và tổng thể nhưng chỉ có thể bù chi phí không gian bằng cách chỉ tăng hai trong ba mảng. Nói cách khác, nén chặt có ý nghĩa hơn khi bạn đã lãng phí không gian cho các khóa, giá trị và giá trị băm. Nếu bạn mất một trong ba điều đó, nó sẽ không còn hấp dẫn nữa.
Mẫu sử dụng cho các bộ khác với dicts. Các cựu có nhiều lượt truy cập hoặc bỏ lỡ. Cái sau có xu hướng thiếu ít tra cứu quan trọng hơn. Ngoài ra, một số tối ưu hóa cho các hoạt động set-to-set gây khó khăn cho việc duy trì thứ tự thiết lập mà không ảnh hưởng đến hiệu suất.
Tôi theo đuổi con đường thay thế để cải thiện hiệu suất thiết lập. Thay vì nén (không chiếm nhiều không gian và phát sinh chi phí cho một lần bổ sung), tôi đã thêm tính năng thăm dò tuyến tính để giảm chi phí va chạm và cải thiện hiệu suất bộ đệm. Cải tiến này không tương thích với phương pháp nén mà tôi ủng hộ cho từ điển.
Hiện tại, tác dụng phụ của thứ tự đối với từ điển là không được bảo đảm, do đó, còn sớm để bắt đầu khẳng định các bộ cũng được đặt hàng. Các tài liệu đã liên kết đến một công thức để tạo một Orderedset (
https://code.activestate.com/recipes/576694/ ) nhưng có vẻ như sự hấp thụ đã gần như bằng không. Ngoài ra, bây giờ Eric Snow đã cho chúng tôi một OrderedDict nhanh chóng, việc xây dựng một Orderedset từ Mutableset và OrderedDict trở nên dễ dàng hơn bao giờ hết, nhưng một lần nữa tôi đã không quan sát thấy bất kỳ mối quan tâm thực sự nào vì các phân tích dữ liệu được thiết lập điển hình không thực sự cần hoặc quan tâm đến việc đặt hàng. Tương tự như vậy, việc sử dụng chính của các bài kiểm tra thành viên nhanh là thuyết bất khả tri.
Điều đó nói rằng, tôi nghĩ có chỗ để thêm các triển khai tập hợp thay thế cho PyPI. Đặc biệt, có một số trường hợp đặc biệt thú vị đối với dữ liệu có thể sắp xếp trong đó các thao tác cài đặt có thể được tăng tốc bằng cách so sánh toàn bộ phạm vi khóa (xem
https://code.activestate.com/recipes/230113-im THỰCation-of- bộ-sử dụng-sắp xếp-danh sách
cho một điểm bắt đầu). IIRC, PyPI đã có mã cho các bộ lọc nở giống như set và băm cuckoo.
Tôi hiểu rằng thật thú vị khi có một khối mã chính được chấp nhận vào lõi Python nhưng điều đó không mở ra cho lũ lụt để tham gia vào việc viết lại nhiều hơn các kiểu dữ liệu khác trừ khi chúng tôi chắc chắn rằng nó được bảo hành.
- Raymond Hettinger
Từ [Python-Dev] Python 3.6 dict trở nên nhỏ gọn và có phiên bản riêng; và từ khóa được đặt hàng , tháng 9 năm 2016.