Упорядочены ли словари в Python 3.6+?
словари упорядочены в Python 3.6 (по крайней мере, при реализации CPython), в отличие от предыдущих воплощений. Это кажется существенным изменением, но это всего лишь короткий абзац в документация. Он описывается как деталь реализации CPython, а не языковая функция, но также подразумевает, что это может стать стандартным в будущем.
как новая реализация словаря работает лучше, чем старая при сохранении элемента порядок?
вот текст из документации:
dict()теперь использует "компактное" представление пионером PyPy. Использование памяти нового dict () составляет от 20% до 25% меньше по сравнению с Python 3.5. PEP 468 (сохранение порядка * * кваргов в функции.) реализуется этим. Сохраняющий порядок аспект этой новой реализации рассматривается как деталь реализации и не следует полагаться (это может быть изменение в будущем, но желательно иметь эту новую реализацию dict на языке для нескольких выпусков, прежде чем изменять спецификацию языка, чтобы поручить семантику сохранения порядка для всех текущих и будущих реализаций Python; это также помогает сохранить обратную совместимость с более старыми версиями языка, где случайный порядок итерации все еще действует, например Python 3.5). (Вклад Инада Наоки в вопрос 27350. Идея первоначально предложил Раймонд Hettinger.)
Обновление Декабрь 2017: dict s сохраняя порядок вставки гарантированный для Python 3.7
3 ответа:
словари упорядочены в Python 3.6+?
они вставки приказал[1]. Начиная с Python 3.6, для реализации CPython Python, словари запомните порядок вставленных элементов. это считается деталью реализации в Python 3.6; вы должны использовать
OrderedDictЕсли вы хотите заказать вставку, это гарантированный через другие реализации Python (и другое упорядоченное поведение[1]).начиная с Python 3.7, это больше не деталь реализации и вместо этого становится функцией языка. из сообщения python-dev от GvR:
сделать так. "Диктатор держит порядок вставки" - это постановление. Спасибо!
это просто означает, что вы можете на это положиться. Другой реализации Python также должны предлагать упорядоченный словарь вставки, если они хотят быть соответствующей реализацией Python 3.7.
как работает питон
3.6реализация словаря работает лучше[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_sizes полный сохраняется. Пустое пространство изменилось с типаPyDictKeyEntryдоintX_t.итак, очевидно, создание разреженного массива типа
PyDictKeyEntryтребует гораздо больше памяти, чем разреженный массив для храненияints.вы можете увидеть полный разговор на Python-Dev что касается этой функции, если интересно, это хорошо читать.
в первоначальном предложении, сделанном Раймондом Hettinger, визуализация используемых структур данных можно увидеть, что передает суть идеи.
например, словарь:
d = {'timmy': 'red', 'barry': 'green', 'guido': 'blue'}в настоящее время хранится в виде:
данные должны быть организованы следующим образом: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]: я говорю "вставка упорядочена", а не "упорядочена", поскольку при существовании OrderedDict "ordered" предполагает дальнейшее поведение, которое
dictобъект не дает. OrderedDicts являются обратимыми, обеспечивают чувствительные к порядку методы и, в основном, обеспечивают тесты на равенство порядка (==,!=).dicts в настоящее время не предлагают ни одного из этих поведений/методов.
[2]: новые словарные реализации работают лучше память мудрого путем быть конструированным более компактно; это главное преимущество здесь. Скорость мудрая, разница не так радикальна, есть места, где новый дикт может ввести небольшие регрессии (key-lookups, например) в то время как в других (итерация и изменение размера приходят на ум) повышение производительности должно быть подарок.
В целом, производительность словаря, особенно в реальных ситуациях, улучшается за счет введенной компактности.
ниже дан ответ на первоначальный первый вопрос:
Я должен использовать
dictилиOrderedDictв Python 3.6?Я думаю, что это предложение из документации на самом деле достаточно, чтобы ответить на ваш вопрос
аспект сохранения порядка этой новой реализации рассматривается как деталь реализации и не следует полагаться на
dictявно не предназначен для упорядоченной коллекции, поэтому если вы хотите оставаться последовательным и не полагаться на побочный эффект новой реализации, которую вы должны придерживатьсяOrderedDict.сделает ваш код в будущем :)
есть дебаты об этом здесь.
EDIT:Python 3.7 сохранит это как функциюпосмотреть
обновление: Гвидо ван Россум объявил в списке рассылки, что по состоянию на Python 3.7
dicts во всех реализациях Python должен сохранять порядок вставки.