python – TypeError: unhashable type: dict

python – TypeError: unhashable type: dict

Youre trying to use a dict as a key to another dict or in a set. That does not work because the keys have to be hashable. As a general rule, only immutable objects (strings, integers, floats, frozensets, tuples of immutables) are hashable (though exceptions are possible). So this does not work:

>>> dict_key = {a: b}
>>> some_dict[dict_key] = True
Traceback (most recent call last):
  File <stdin>, line 1, in <module>
TypeError: unhashable type: dict

To use a dict as a key you need to turn it into something that may be hashed first. If the dict you wish to use as key consists of only immutable values, you can create a hashable representation of it like this:

>>> key = frozenset(dict_key.items())

Now you may use key as a key in a dict or set:

>>> some_dict[key] = True
>>> some_dict
{frozenset([(a, b)]): True}

Of course you need to repeat the exercise whenever you want to look up something using a dict:

>>> some_dict[dict_key]                     # Doesnt work
Traceback (most recent call last):
  File <stdin>, line 1, in <module>
TypeError: unhashable type: dict
>>> some_dict[frozenset(dict_key.items())]  # Works
True

If the dict you wish to use as key has values that are themselves dicts and/or lists, you need to recursively freeze the prospective key. Heres a starting point:

def freeze(d):
    if isinstance(d, dict):
        return frozenset((key, freeze(value)) for key, value in d.items())
    elif isinstance(d, list):
        return tuple(freeze(value) for value in d)
    return d

A possible solution might be to use the JSON dumps() method, so you can convert the dictionary to a string —

import json

a={a:10, b:20}
b={b:20, a:10}
c = [json.dumps(a), json.dumps(b)]


set(c)
json.dumps(a) in c

Output –

set([{a: 10, b: 20}])
True

python – TypeError: unhashable type: dict

Leave a Reply

Your email address will not be published. Required fields are marked *