Сохраняется ли порядок элементов в set и dict в Python
Что проверяют
Отличаете ли вы гарантию языка от детали реализации. Вопрос короткий, но разделяет тех, кто читал документацию, и тех, кто сделал вывод из вывода в консоли.
Как отвечать
dict сохраняет порядок вставки, и начиная с Python 3.7 это гарантия языка, а не особенность конкретной сборки. В CPython 3.6 так уже работало, но считалось деталью реализации. Порядок именно вставки: присваивание по существующему ключу его не меняет, а удаление и повторная вставка перемещают ключ в конец.
set порядка не сохраняет вообще. Элементы лежат в хеш-таблице, и обход зависит от значений хешей, размера таблицы и истории вставок и удалений. То, что множество из трёх небольших целых печатается по возрастанию, это не порядок вставки и не сортировка: у целого числа хеш равен ему самому, и элементы просто попадают в ячейки по порядку. Со строками картина другая: хеш строки рандомизируется при каждом запуске процесса, поэтому обход множества строк меняется от запуска к запуску.
d = {"b": 1, "a": 2}
list(d) # всегда ['b', 'a']
list({"b", "a"}) # порядок не определён
list(dict.fromkeys(seq)) # дедупликация с сохранением порядкаЕсли порядок нужен по смыслу, его надо задать явно: sorted, список рядом с множеством, dict.fromkeys для дедупликации.
Где спотыкаются
Переносят гарантию со словаря на множество и говорят, что set тоже упорядочен. Это неверно, и никакой версией это не подтверждается.
Полагаются на порядок множества в тестах и в сериализации. Локально тест зелёный, в другом процессе или на другом наборе данных он краснеет, и причину ищут в бизнес-логике.
Списывают OrderedDict как ненужный. Он всё ещё отличается от dict: сравнение учитывает порядок, и есть move_to_end, на котором удобно строить кэш с вытеснением.