Чи впорядковані словники в Python 3.6+?
Вони впорядковані [1] . Як і в Python 3.6, для реалізації CPython Python словники запам'ятовують порядок вставлених елементів . Це вважається деталізацією реалізації в Python 3.6 ; вам потрібно скористатися, OrderedDict
якщо ви хочете впорядкувати вставку, що гарантується в інших реалізаціях Python (та інших впорядкованих поведінках [1] ).
Як і в Python 3.7 , це більше не є деталізацією реалізації, а натомість стає мовною особливістю. З повідомлення пітона-розробника GvR :
Зробіть так. "Дикт зберігає порядок вставки" є постановою. Дякую!
Це просто означає, що ви можете від цього залежати . Інші реалізації Python також повинні пропонувати словник із упорядкованою вставкою, якщо вони хочуть бути відповідною реалізацією Python 3.7.
Як 3.6
реалізація словника Python працює краще [2], ніж старша, зберігаючи порядок елементів?
По суті, зберігаючи два масиви .
Перший масив, dk_entries
містить записи ( типуPyDictKeyEntry
) для словника в тому порядку, в який вони були вставлені. Порядок збереження досягається тим, що це лише додавання масиву, де нові елементи завжди вставляються в кінці (порядок вставки).
Другий, dk_indices
містить dk_entries
вміст індексів для масиву (тобто значень, що вказують на позицію відповідного запису в dk_entries
). Цей масив виконує функції хеш-таблиці. Коли хеширований ключ, він призводить до одного з індексів, що зберігаються, dk_indices
і відповідний запис вибирається шляхом індексації dk_entries
. Оскільки зберігаються лише індекси, тип цього масиву залежить від загального розміру словника (починаючи з типу int8_t
( 1
байт) до int32_t
/ int64_t
( 4
/ 8
байтів) у 32
/ 64
бітових збірках)
У попередній реалізації мала бути виділена розріджена матриця типу PyDictKeyEntry
та розміру dk_size
; на жаль, це також призвело до багато порожнього простору, оскільки цей масив не міг бути більш ніж 2/3 * dk_size
заповненим з міркувань продуктивності . (а порожній простір ще мав PyDictKeyEntry
розмір!).
Зараз це не так, оскільки зберігаються лише необхідні записи (ті, які були вставлені), і розріджений тип масиву intX_t
( X
залежно від розміру диктату) 2/3 * dk_size
зберігається повним. Порожній простір змінився від типу PyDictKeyEntry
до intX_t
.
Отже, очевидно, створення розрідженого типу масиву PyDictKeyEntry
набагато більш вимогливо до пам'яті, ніж розріджений масив для зберігання int
s.
Ви можете побачити повну розмову на Python-Dev щодо цієї функції, якщо зацікавлено, це добре читати.
У оригінальній пропозиції Реймонда Хеттінгера видно візуалізацію використаних структур даних, яка фіксує суть ідеї.
Наприклад, словник:
d = {'timmy': 'red', 'barry': 'green', 'guido': 'blue'}
наразі зберігається як [keyhash, key, value]:
entries = [['--', '--', '--'],
[-8522787127447073495, 'barry', 'green'],
['--', '--', '--'],
['--', '--', '--'],
['--', '--', '--'],
[-9092791511155847987, 'timmy', 'red'],
['--', '--', '--'],
[-6480567542315338377, 'guido', 'blue']]
Натомість дані мають бути організовані таким чином:
indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
Як візуально зараз ви бачите, в оригінальній пропозиції багато місця по суті порожнє, щоб зменшити зіткнення та зробити огляд швидше. З новим підходом ви зменшуєте необхідну пам'ять, переміщуючи обмеженість, де це дійсно потрібно, в індексах.
[1]: Я кажу "впорядкована вставка", а не "впорядкована", оскільки, з існуванням OrdersDict, "впорядковано" передбачає подальшу поведінку, яку dict
об'єкт не передбачає . OrdersDicts є оборотними, забезпечують методи, що залежать від порядку, і, головним чином, забезпечують тести рівності для замовлень ( ==
, !=
). dict
На даний момент не пропонують жодної з цих форм поведінки / методів.
[2]: Нові реалізації словника покращують об'єм пам'яті , розробляючись більш компактно; ось головна вигода тут. Швидка швидкість, різниця не настільки драматична, є місця, де новий диктант може ввести незначні регресії (наприклад, пошук ключів ), а в інших (ітерація та зміна розміру приходять на думку) має бути присутнім підвищення продуктивності.
В цілому ефективність словника, особливо в реальних ситуаціях, покращується завдяки введеній компактності.