Ответ 1
Порядок dict определяется полностью хеширующей функцией объекта (и порядком вставки, если есть хеш-коллизии). Целые хэши сами по себе (по крайней мере, до sys.maxint
):
>>> hash(1)
1
Реализация python (C) принимает хэш-значение объекта и принимает несколько бит, чтобы определить индекс в таблице. Количество бит, которое требуется, зависит от длины словаря. По умолчанию у dict есть 8 доступных слотов, поэтому числа 0
и 8
будут сталкиваться. Мы можем видеть это следующим образом:
>>> d1 = {}
>>> d1[0] = 'foo'
>>> d1[8] = 'bar'
>>> d1
{0: 'foo', 8: 'bar'}
>>>
>>> d2 = {}
>>> d2[8] = 'bar'
>>> d2[0] = 'foo'
>>> d2
{8: 'bar', 0: 'foo'}
Так как 0
и 8
сталкиваются в нашем словаре, порядок вставки, как представляется, сохраняется. 0
занимает первый доступный слот (в конце концов, независимо от того, сколько бит вы берете с 0
, вы получите 0
). 8
пытается взять этот слот. Однако, если этот слот взят, разрешение конфликтов возникает, а python вставляет это значение в некоторый более поздний слот.
Конечно, если ваш словарь имеет более чем 5 элементов, он будет изменен (я думаю, до 16, но не цитирую меня), а 0
и 8
больше не будут сталкиваться...
>>> d1 = {x:x for x in range(1, 6)}
>>> d1[0] = 0
>>> d1[8] = 8
>>> d1
{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 8: 8}
>>> d2 = {x:x for x in range(1, 6)}
>>> d2[8] = 8
>>> d2[0] = 0
>>> d2
{0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 8: 8}
Обратите внимание, что порядок сортировки сохраняется (не порядок вставки), что означает, что каждое целое число получило предпочтительное место в хеш-таблице (без коллизий). Я думаю, что размер бита изменяется, когда он равен 2/3rds.
Обратите внимание, что это чисто академическое - спецификация python не говорит, что это так, как это работает, и поэтому оно может измениться в любое время. Пожалуйста, не полагайтесь на это поведение. Большинство из них можно почерпнуть из комментариев в исходном коде и документация, который находится рядом с ним...