Начиная с Python 3.7 словари стали упорядоченными
С самого первого издания “Learning Python” от Марка Лутца, нас учили, что словари в python не упорядочены. Но начиная с версии 3.6, для реализации CPython, ситуация поменялась. Разработчики изменили реализацию словаря и одной из особенности нового подхода стало упорядочивание ключей словаря. А с версии 3.7 эта особенность стала официальной фитчей.
Почему новая реализация лучше чем старая?
Сохранение порядка при вставке не было самой целью, с самого начала новая реализация преследовала идеи экономии памяти и ускорение работы.
Основная идея в следующем, в реализации словаря до 3.6 использовался разряженный массив, элементом которого был довольно большой объект, PyDictKeyEntry
. А так как все элементы в массиве должны быть одного размера, пустые и не пустые элементы занимали память одинаковое количество памяти.
hash | key | value |
---|---|---|
hash1 | foo | bar |
# | # | # |
# | # | # |
hash2 | bar | foo |
# | # | # |
hash3 | sed | cat |
# | # | # |
В новой реализации используются два массива. Первый сохраняет записи в том порядке в котором они были вставлены. Второй, содержит индексы для первого массива и работает как хеш таблица: ключ хешируется, получаем индекс для первого массива из второго, далее получаем само значение.
index |
---|
0 |
# |
# |
1 |
# |
2 |
hash | key | value |
---|---|---|
hash1 | foo | bar |
hash2 | bar | foo |
hash3 | sed | cat |
По итогу кол-во потребляемой памяти уменьшилось, так как разряженный массив теперь хранит только числа, а не значение полностью.
По итогу словари используют меньше памяти, и как плюс стали упорядочены.
OrderedDict не нужен?
Во-первых, явное лучше, чем неявное, поэтому если в вашем конкретном кейсе нужен упорядоченный словарь, лучше использовать OrderedDict
. Во-вторых, если полагаться на новую реализацию, нарушится обратная совместимость, и код перестанет работать на версии 3.5 и ниже.
Итого
Любое улучшение в языке это всегда круто и полезно, но конкретно это изменение несет и небольшую опасность, по больше части для разработчиков, которые только начинают знакомиться с python. На курсах и даже в учебниках часто опускают влияние версии на функциональность языка и описывают ситуацию на текущий момент, и можно быстро привыкнуть к упорядоченному словарю. И уже в реальной работе, где может быть python 3.5 допустить ошибку, и если нет тестов, то все может закончится печально. Поэтому в данный момент лучше держать информацию о новой реализации словаря как полезный факт.