Использование Tuples и Frozensets в качестве ключей словаря в Python
Tuples и frozensets — это неизменяемые т. е. неизменяемые версии списков и наборов соответственно. Одним из преимуществ неизменности является то, что эти структуры данных хешируются. Таким образом, для кортежа и замороженного набора может быть уникальный хэш. Это также означает, что их можно использовать в качестве ключей в словаре, в то время как их изменяемые аналоги, то есть списки и наборы, нельзя использовать в качестве ключей словаря.
Почему они хешируются?
Поскольку эти типы данных являются неизменяемыми, это означает, что после их создания значения не могут быть изменены, и поэтому значение хеш-функции всегда будет одним и тем же.
>>> my_set = set([1, 2, 1, 3]) >>> hash(my_set) # set cannot be hashed! Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unhashable type: 'set' >>> my_frozenset = frozenset([1, 2, 1, 3]) >>> hash(my_frozenset) -272375401224217160 >>> another_frozenset = frozenset([1, 2, 3, 1]) >>> hash(another_frozenset) # Hash value should be same as before as elements are the same -272375401224217160 >>> my_tuple = (1, 2, 1, 3) >>> hash(my_tuple) -3261335203891832775 >>> my_tuple = (1, 2, 3, 1) >>> hash(my_tuple) # hash values of the tuples are different as the order of elements are different -3132950713063864564
Когда использовать кортежи и замороженные наборы в качестве ключей словаря?
При использовании в словаре использование этих типов имеет значение.
Если порядок элементов в ключе имеет значение, то в качестве ключа словаря следует использовать кортежи.
Если порядок элементов в ключе не имеет значения, а дубликаты можно игнорировать, то в качестве ключа словаря можно использовать замороженный набор.
>>> dict1 = {(1,2): "ab", (2,1):"cd"} >>> (1,2) in dict1 # Check if the tuple exists in the dictionary dict1 True >>> dict1 # 2 different elements as order of elements in a Tuple matters {(1, 2): 'ab', (2, 1): 'cd'} >>> dict3={frozenset([1,2]):"ab"} >>> dict3[frozenset([2,1,1])]="cd" # Update existing element in the dictionary >>> dict3 {frozenset({1, 2}): 'cd'} >>> frozenset([2,1]) in dict3 True >>> frozenset([1,2]) in dict3 True >>> frozenset([1,2,2,1]) in dict3 # Order of items and duplicates are ignored True