TypeError: unhashable type: 'dict' (Python)

avatar

Borislav Hadzhiev

Last updated: Apr 20, 2022

banner

Photo from Unsplash

TypeError: unhashable type: 'dict' (Python) #

The Python "TypeError: unhashable type: 'dict'" occurs when we use a dictionary as a key in another dictionary or as an element in a set. To solve the error, use a frozenset instead, or convert the dictionary into a JSON string before using it as a key.

typeerror unhashable type dict

Here are 2 examples of how the error occurs.

main.py
# 👇️ using dictionary as a key in a dictionary # ⛔️ TypeError: unhashable type: 'dict' my_dict = {'name': 'Alice', {'country': 'Austria'}: 'address'} # 👇️ using dictionary as an element in a set # ⛔️ TypeError: unhashable type: 'dict' my_set = {{'name': 'Alice'}}
We can't use a dictionary as a key in a dictionary or as an element in a set because dict objects are mutable and unhashable.

One way to solve the error is to use a frozenset.

main.py
my_key = {'country': 'Austria'} key = frozenset(my_key.items()) print(key) # 👉️ frozenset({('country', 'Austria')}) my_dict = {'name': 'Alice', key: 'address'} # 👇️ when you have to access the key print(my_dict[frozenset(my_key.items())]) # 👉️ 'address'

The dict.items method returns a new view of the dictionary's items ((key, value) pairs).

We used the dictionary's items to create a frozenset which we can use as a key in a dictionary (and an element in another set).

A frozenset is an immutable version of the Python set object, so it can be used as a key in a dictionary or an element in another set.

Notice that you have to use the same approach to access the key in the dictionary.

You can store the result of calling frozenset(my_key.items()) in a variable and reuse the frozenset when setting or accessing the key in the dictionary.

An alternative approach is to convert the dictionary to a JSON string before using it as a key.

main.py
import json # 👇️ convert dictionary to JSON string my_json = json.dumps({'country': 'Austria'}) my_dict = {'name': 'Alice', my_json: 'address'} print(my_dict) # 👉️ {'name': 'Alice', '{"country": "Austria"}': 'address'} # 👇️ when you have to access the key in the dictionary print(my_dict[json.dumps({'country': 'Austria'})]) # 👉️ address

The json.dumps method converts a Python object to a JSON formatted string. This works because strings are immutable and hashable.

Conversely, the json.loads method parses a JSON string into a native Python object, e.g. my_dict = json.loads(my_json_str).

Most of the immutable built-in objects in Python are hashable, whereas mutable objects are unhashable.

If an object is hashable, then it can be used as a key in a dictionary and as an element in a set, because these data structures use the hash value internally.

Hashable objects include - str, int, bool, tuple, frozenset.

Unhashable objects include - list, dict, set.

Note that tuples and frozensets are only hashable if their elements are hashable.

You can check if an object is hashable by passing it to the built-in hash() function.

main.py
print(hash('hello')) # 👉️ -1210368392134373610 # ⛔️ TypeError: unhashable type: 'dict' print(hash({'name': 'Alice'}))

The hash function returns the hash value of the passed-in object (if it has one).

Hash values are integers and are used to compare dictionary keys during a dictionary lookup.

Hashable objects have a hash value that never changes during their lifetime. This is why most immutable objects are hashable, whereas mutable ones are unhashable.

Objects like dictionaries are mutable because the contents of a dict can be changed.

main.py
my_dict = {'name': 'Alice'} my_dict['name'] = 'Bob' print(my_dict) # 👉️ {'name': 'Bob'}

On the other hand, fronzenset and tuple objects that contain primitive values are immutable (and hashable).

Dictionaries are indexed by keys and the keys in a dictionary can be any immutable type, e.g. strings or numbers.

Tuples can only be used as keys in a dictionary if they contain strings, numbers or tuples.

If a frozenset or a tuple contains mutable objects such as lists, it cannot be used as a key in a dictionary or an element in a set.

If you aren't sure what type of object a variable stores, use the type() class.

main.py
my_dict = {'name': 'Alice'} print(type(my_dict)) # 👉️ <class 'dict'> print(isinstance(my_dict, dict)) # 👉️ True my_str = 'hello' print(type(my_str)) # 👉️ <class 'str'> print(isinstance(my_str, str)) # 👉️ True

The type class returns the type of an object.

The isinstance function returns True if the passed in object is an instance or a subclass of the passed in class.

Conclusion #

The Python "TypeError: unhashable type: 'dict'" occurs when we use a dictionary as a key in another dictionary or as an element in a set. To solve the error, use a frozenset instead, or convert the dictionary into a JSON string before using it as a key.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.