2016-01-05 3 views
1

Если у нас есть 2 отдельных dict, оба с одинаковыми keys и values, когда мы их напечатаем, он поступит в разных заказах, как и ожидалось.
Итак, давайте скажем, я хочу, чтобы использовать hash() на тех dict:Python - hash() и dict

hash(frozenset(dict1.items())) 
hash(frozenset(dict2.items())) 

Я делаю это, чтобы сделать новую dict со значением hash(), созданного в качестве новых ключей.
Даже показывая разные при печати dict, значение createad на hash() будет равно быть равным? Если нет, как сделать его всегда одинаковым, чтобы я мог успешно проводить сравнения?

+0

Итак, рассмотрите' key1' из 1-й строки и 'key2' со 2-го. Если я делаю 'if (key1 == key1)' всегда будет true? Просто убедившись, сожалею о моем отсутствии опыта. –

+2

Зачем им приходить в разных заказах? Нет никакой случайности в правильности вставки хеширования * или * словаря? –

+0

Ну, 'dicts' не имеют указанного порядка? Мне интересно, может ли это изменить значение 'hash' –

ответ

3

Если ключи и значения hash одинаковы, то frozenset предназначен для стабильного и уникального представления базовых значений. The docs explicitly state:

Два набора равны тогда и только тогда, когда каждый элемент каждого набора содержится в другом (каждый из них является подмножеством другого).

И the rules for hashable types require that:

Hashable объекты, которые сравнивают равно должны иметь одинаковое значение хеш-функции.

Таким образом, по определению frozenset s с равными, хешируемыми элементами равны и хэш с одинаковым значением. Это может быть нарушено только в том случае, если пользовательский класс, который не подчиняется правилам хэширования и равенства, содержится в полученном frozenset (но тогда у вас больше проблем).

Обратите внимание, что это не означает, что они будут выполнять итерацию в том же порядке или производить то же самое repr; благодаря привязке к хэш-коллизиям, два frozenset s, построенные из одних и тех же элементов в другом порядке, не должны перебираться в том же порядке. Но они по-прежнему равны друг другу, а хэш - то же самое (точные выходы и упорядочение зависят от реализации, могут легко варьироваться в зависимости от разных версий Python: это просто работает с моей установкой Py 3.5 для создания желаемого «итерационного порядка» «поведение):

>>> frozenset([1,9]) 
frozenset({1, 9}) 
>>> frozenset([9,1]) 
frozenset({9, 1}) # <-- Different order; consequence of 8 buckets colliding for 1 and 9 
>>> hash(frozenset([1,9])) 
-7625378979602737914 
>>> hash(frozenset([9,1])) 
-7625378979602737914 # <-- Still the same hash though 
>>> frozenset([1,9]) == frozenset([9,1]) 
True # <-- And still equal