Từ điển có được đặt hàng trong Python 3.6+ không?
Họ được đặt đặt hàng [1].insertion ordered[1].
Kể từ Python 3.6, đối với việc triển khai Python Cpython, từ điển hãy nhớ thứ tự của các mục được chèn vào. Đây được coi là một chi tiết thực hiện trong Python 3.6; Bạn cần sử dụng OrderedDict
nếu bạn muốn đặt hàng chèn được đảm bảo trong các triển khai khác của Python [và hành vi được đặt hàng khác [1]]., for the CPython implementation of Python, dictionaries remember the order of items inserted. This is considered an implementation detail in Python 3.6; you need to use OrderedDict
if you want insertion ordering that's guaranteed across other
implementations of Python [and other ordered behavior[1]].
Kể từ Python 3.7, đây là một tính năng ngôn ngữ được đảm bảo, không chỉ là một chi tiết triển khai. Từ một tin nhắn Python-Dev của GVR:, this is a guaranteed language feature, not merely an implementation detail. From a python-dev message by GvR:
Làm cho nó như vậy. "Dict giữ lệnh chèn" là phán quyết. Cảm ơn!
Điều này đơn giản có nghĩa là bạn có thể phụ thuộc vào nó. Các triển khai khác của Python cũng phải cung cấp một từ điển được đặt hàng chèn nếu họ muốn trở thành một triển khai phù hợp của Python 3.7.
Làm thế nào để triển khai từ điển Python
3.6
hoạt động tốt hơn [2] so với cái cũ hơn trong khi bảo tồn thứ tự phần tử?
Về cơ bản, bằng cách giữ hai mảng.
Mảng đầu tiên,
dk_entries
, giữ các mục [loạiPyDictKeyEntry
] cho từ điển theo thứ tự mà chúng được chèn. Lệnh bảo tồn đạt được bằng cách này là một mảng chỉ nối trong đó các mục mới luôn được chèn vào cuối [thứ tự chèn].Thứ hai,
dk_indices
, giữ các chỉ số cho mảngdk_entries
[nghĩa là các giá trị chỉ ra vị trí của mục nhập tương ứng trongdk_entries
]. Mảng này hoạt động như bảng băm. Khi một khóa được băm, nó dẫn đến một trong các chỉ số được lưu trữ trongdk_indices
và mục nhập tương ứng được tìm nạp bằng cách lập chỉ mụcdk_entries
. Vì chỉ các chỉ số được giữ, loại mảng này phụ thuộc vào kích thước tổng thể của từ điển [từ loại ____ 12 [________ 13 byte] đến ________ 14/________ 15 [________ 16/________ 17 Byte]
Trong quá trình triển khai trước đó, một mảng thưa thớt của loại
indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
0 và kích thước indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
1 phải được phân bổ; Thật không may, nó cũng dẫn đến rất nhiều không gian trống vì mảng đó không được phép nhiều hơn indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
2 vì lý do hiệu suất. [Và không gian trống vẫn có kích thước indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
0!].Đây không phải là trường hợp bây giờ vì chỉ các mục được yêu cầu được lưu trữ [những mục đã được chèn] và một mảng thưa thớt của loại
indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
4 [indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
5 tùy thuộc vào kích thước dict] indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
2S được giữ lại. Không gian trống thay đổi từ loại indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
0 thành indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
4.
Vì vậy, rõ ràng, việc tạo ra một mảng thưa thớt của loại
indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
0 đòi hỏi nhiều hơn nhiều so với một mảng thưa thớt để lưu trữ OrderedDict
0s.Bạn có thể thấy cuộc trò chuyện đầy đủ trên Python-dev liên quan đến tính năng này nếu quan tâm, đó là một bài đọc tốt.
Trong đề xuất ban đầu được thực hiện bởi Raymond Hettinger, một hình ảnh của các cấu trúc dữ liệu được sử dụng có thể được nhìn thấy để nắm bắt ý chính của ý tưởng.
Ví dụ: Từ điển:
d = {'timmy': 'red', 'barry': 'green', 'guido': 'blue'}
hiện được lưu trữ dưới dạng [Keyhash, Key, Giá trị]:
entries = [['--', '--', '--'], [-8522787127447073495, 'barry', 'green'], ['--', '--', '--'], ['--', '--', '--'], ['--', '--', '--'], [-9092791511155847987, 'timmy', 'red'], ['--', '--', '--'], [-6480567542315338377, 'guido', 'blue']]
Thay vào đó, dữ liệu nên được tổ chức như sau:
indices = [None, 1, None, None, None, 0, None, 2] entries = [[-9092791511155847987, 'timmy', 'red'], [-8522787127447073495, 'barry', 'green'], [-6480567542315338377, 'guido', 'blue']]
Như bạn có thể thấy trực quan bây giờ, trong đề xuất ban đầu, rất nhiều không gian về cơ bản là trống rỗng để giảm va chạm và làm cho việc tra cứu nhanh hơn. Với cách tiếp cận mới, bạn giảm bộ nhớ theo yêu cầu bằng cách di chuyển sự thưa thớt nơi nó thực sự cần thiết, trong các chỉ số.
. Các thứ tự có thể đảo ngược, cung cấp các phương pháp nhạy cảm theo thứ tự và, chủ yếu, cung cấp một bài kiểm tra bình đẳng về thứ tự [`==`, `! =`]. Hiện tại không cung cấp bất kỳ hành vi/phương pháp nào.
[2]: Việc triển khai từ điển mới thực hiện tốt hơn ** bộ nhớ khôn ngoan ** bằng cách được thiết kế nhỏ gọn hơn; Đó là lợi ích chính ở đây. Tốc độ khôn ngoan, sự khác biệt không quá quyết liệt, có những nơi mà Dict mới có thể giới thiệu các hồi quy nhẹ [ví dụ như lookups] trong khi ở những người khác [lặp lại và thay đổi kích thước xuất hiện trong tâm trí]. Nhìn chung, hiệu suất của từ điển, đặc biệt là trong các tình huống thực tế, được cải thiện do sự nhỏ gọn được giới thiệu.