In Python, when you want to use lists as keys of some dictionary, you can turn them into tuples, which are immutable and hence are hashable.
>>> a = {} >>> a[tuple(list_1)] = some_value >>> a[tuple(list_2)] = some_other_value
The same happens when you want to use set objects as keys of some dictionary - you can build a frozenset, that is again immutable and hence is hashable.
>>> a = {} >>> a[frozenset(set_1)] = some_value >>> a[frozenset(set_2)] = some_other_value
But it seems that for dictionary there is no equivalent.
A first idea I thought about (and found it bad finally), is to use str(some_dict)
as a key. But, dictionaries always use different hash functions (which affects the order of elements), so strings of equal dictionaries may be different.
Is there any workaround known as a good practice, or does anyone have other ideas how to use dictionary-like objects as keys of other dictionaries?
Starting from Python 3.6, dictionaries preserve the insertion order. Therefore, the workaround would vary depending on the used Python version.
For Python < 3.6 (Dictionaries do not preserve insertion order) - use frozenset, so that two sets are equal even if order is different:
>>> a = {'key1' : 'val1', 'key2' : 'val2'} >>> b = frozenset(a.items()) >>> frozenset_restored_to_dict = dict(b) >>> frozenset_restored_to_dict {'key2': 'val2', 'key1': 'val1'}
Otherwise (Dictionaries preserve insertion order), use tuple. This way, the dictionary can be restored while preserving the order of items, yet, tuples with same items ordered differently will not be equal. A workaround for it would be passing the tuples to a frozenset constructor each time before a comparison is made.
>>> a = {'key1' : 'val1', 'key2' : 'val2'} >>> b = tuple(a.items()) >>> tuple_restored_to_dict = dict(b) >>> tuple_restored_to_dict {'key1': 'val1', 'key2': 'val2'}
As can be seen in the code, b
is a tuple, or a frozenset. Either are immutable and hashable, and can be totally restored to be a regular dictionary like a
.
You can try ordered dict or look on these answers:
and there is even a package on PyPI: https://pypi.python.org/pypi/frozendict
You can also simply convert dict to tuples(sorted(your_dict.items())
) and then use as a hash.
UPD: as mentioned in comments, OrderedDict is unhashable. My bad, it is really should not be hashable since it is mutable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With