TypeError: unhashable type: 'dict' in Python [Solved]

avatar
Borislav Hadzhiev

Last updated: Apr 8, 2024
5 min

banner

# TypeError: unhashable type: 'dict' in Python [Solved]

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

The error occurs when you use a dictionary as a key in another dictionary.

main.py
# ๐Ÿ‘‡๏ธ Using a dictionary as a key in a dictionary # โ›”๏ธ TypeError: unhashable type: 'dict' my_dict = {'name': 'Bobby', {'country': 'Austria'}: 'address'}

Or when you use a dictionary as an element in a set object.

main.py
# ๐Ÿ‘‡๏ธ Using a dictionary as an element in a set # โ›”๏ธ TypeError: unhashable type: 'dict' my_set = {{'name': 'Bobby'}}
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.

# Convert the dictionary to a JSON string to solve the error

One way to solve the error is to convert the dictionary to a JSON string before using it as a key.

main.py
import json # ๐Ÿ‘‡๏ธ Convert the dictionary to JSON string my_json = json.dumps({'country': 'Austria'}) my_dict = {'name': 'Bobby', my_json: 'address'} print(my_dict) # ๐Ÿ‘‰๏ธ {'name': 'Bobby', '{"country": "Austria"}': 'address'} # ๐Ÿ‘‡๏ธ when you have to access the key in the dictionary print(my_dict[json.dumps({'country': 'Austria'})]) # ๐Ÿ‘‰๏ธ address

convert dictionary to json string to solve the error

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).

# Using a frozenset to solve the error

An alternative 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': 'Bobby', key: 'address'} # ๐Ÿ‘‡๏ธ When you have to access the key print(my_dict[frozenset(my_key.items())]) # ๐Ÿ‘‰๏ธ 'address'

using frozenset to solve the error

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

main.py
# ๐Ÿ‘‡๏ธ dict_items([('name', 'bobby'), ('age', 30)]) print({'name': 'bobby', 'age': 30}.items())

We used the dictionary's items to create a frozenset that 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.

# Converting the dictionary to a tuple to solve the error

Another way to solve the error is to convert the dictionary to a tuple.

main.py
dict_key = {'id': 1, 'country': 'Austria'} # โœ… Convert to tuple my_tuple = tuple(dict_key) print(my_tuple) # ๐Ÿ‘‰๏ธ ('id', 'country') my_dict = {'name': 'Bobby', my_tuple: 'address'} print(my_dict) # ๐Ÿ‘‰๏ธ {'name': 'Bobby', ('id', 'country'): 'address'} # ๐Ÿ‘‡๏ธ When you have to access the key in the dictionary print(my_dict[my_tuple]) # ๐Ÿ‘‰๏ธ address

converting the dictionary to tuple to solve the error

When you convert a dictionary to a tuple, the tuple only contains the keys of the dictionary.

Tuples are immutable, so a tuple containing a dictionary's keys can safely be used as a key in another dictionary.

# Using one dictionary as a value in another dictionary

You can't use a dictionary as a key in another dictionary, but you can use one as a value.

main.py
dict_value = {'id': 1, 'country': 'Austria'} my_dict = {'name': 'Bobby', 'data': dict_value} # ๐Ÿ‘‡๏ธ {'name': 'Bobby', 'data': {'id': 1, 'country': 'Austria'}} print(my_dict) print(my_dict['data']) # ๐Ÿ‘‰๏ธ {'id': 1, 'country': 'Austria'}

using one dictionary as value in another dictionary

We set one dictionary as a value in another dictionary.

This is allowed as the restrictions don't apply to dictionary values.

# Adding all of the key-value pairs of one dictionary to another

You can use a for loop if you need to add all of the key-value pairs of one dictionary to another.

main.py
another_dict = {'id': 1, 'country': 'Austria'} my_dict = {'name': 'Bobby'} for key, value in another_dict.items(): my_dict[key] = value # ๐Ÿ‘‡๏ธ {'name': 'Bobby', 'id': 1, 'country': 'Austria'} print(my_dict)

adding all of the key value pairs of one dictionary to another

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

main.py
my_dict = {'id': 1, 'name': 'BobbyHadz'} # ๐Ÿ‘‡๏ธ dict_items([('id', 1), ('name', 'BobbyHadz')]) print(my_dict.items())

On each iteration, we set the key-value pair to the other dictionary.

# Hashable vs Unhashable objects in Python

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.

# Checking if an object is hashable

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

main.py
print(hash('bobbyhadz.com')) # ๐Ÿ‘‰๏ธ 4905958875846995527 # โ›”๏ธ TypeError: unhashable type: 'dict' print(hash({'name': 'Bobby Hadz'}))

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'] = 'Bobby Hadz' print(my_dict) # ๐Ÿ‘‰๏ธ {'name': 'Bobby Hadz'}

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': 'Bobby Hadz'} print(type(my_dict)) # ๐Ÿ‘‰๏ธ <class 'dict'> print(isinstance(my_dict, dict)) # ๐Ÿ‘‰๏ธ True my_str = 'bobbyhadz.com' 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.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

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.

Copyright ยฉ 2024 Borislav Hadzhiev