About "TypeError: unhashable type: ‘dict'” in Python

About "TypeError: unhashable type: ‘dict'” in Python

The “TypeError: unhashable type: ‘dict'” error occurs if you use a dictionary where a hashable object is expected.

Update: This post was originally published on my blog decodingweb.dev, where you can read the latest version for a 💯 user experience. ~reza

Whether you’re learning to code, or you’re already a Pythonista, you might encounter this error if:

  • You use a dictionary as the key in another dictionary

  • You want to store a dictionary in a Python Set

  • You pass a dictionary to the hash() function

The error looks like this:

Traceback (most recent call last):
 File "", line 1, in 
TypeError: unhashable type: 'dict'

As you can see, the error message is accompanied by the line number (under "traceback most recent call last file").

But what are hashable objects? You may ask.

Based on Python.org:

An object is hashable if it has a hash value that never changes during its lifetime (it needs a __hash__() method), and can be compared to other objects (it needs an __eq__() method). Hashable objects which compare equal must have the same hash value.

An unhashable object in Python can't have a fixed hash value that remains constant during its lifetime.

Python uses a hash value internally to efficiently look up items in a set or dictionary. When an unhashable object is added to a set or used as a key in a dictionary, a TypeError is raised because the object's hash value can change (when we add/remove items), making it impossible to retrieve the correct value from the set or dictionary.

Below are three facts to know about hashable objects in Python:

#1Most of Python’s immutable built-in objects (strings, numeric values, etc.) are hashable.
#2Immutable objects (such as tuples and frozensets) are only hashable if their elements are hashable.
#3Mutable containers such as lists or dictionaries aren't hashable.

Simply put, Python "typeerror unhashable type" occurs whenever you use a dictionary or list where Python expects a string or numeric value.

Similarly, if you use a list as a key, you would get the "TypeError: unhashable type: 'list'" error. Just like dictionaries, lists are mutable.

How to fix TypeError: unhashable type: 'dict' in Python

If you're getting this error while using a dictionary as a key in another dictionary, give your design decision a second thought!

Ask you yourself why do you need to use the whole dictionary as a key? Sometimes you can pluck a value out of that dictionary and use it as the key.

Imagine we have a list object that contains multiple dictionaries. These dictionaries contain information about programming books in a bookstore.

We also have an inventory dictionary, which we want to initialize with 10 items per book.

You might want to do it like so:

books = [
   { 
      'title': 'Elquent JavaScript',
      'isbn': '9781593279509' 
   },
   { 
      'title': 'Learning Python',
      'isbn': '9781449355739'
   },
   { 
      'title': 'Head First Python',
      'isbn': '9781491919538'
   }
]

inventory = {}

for book in books:
  inventory[book] = 10

The above code would raise the TypeError because the book variable in each iteration is a dict object.

But what if we could take each book's unique ISBN and use it as the key?

# books = ...

inventory = {}

for book in books:
  inventory[book['isbn']] = 10

print(inventory)
# output: {'9781593279509': 10, '9781449355739': 10, '9781491919538': 10}

Well, that's much better! And we won't get the error.

However, if you really need to use a Python dictionary as the key, you must make it hashable first - by converting the dictionary to a tuple.

Here's how you would do it with a tuple:

inventory = {}

for book in books:
  book_hash = tuple(book.items())
  inventory[book_hash] = 10

If you have a list, you can also convert the list to a tuple to make it hashable.

This works, if that's what you want! There's a catch, though!

We can only use tuples (or frozensets) if items in the dictionary are all hashable. If the dictionary contains sub-dictionaries, we might have to take a recursive approach to make it hashable.

Once your dictionaries become hashable, you can store them in Python sets too.

Problem solved 👍.

Alright, that does it! I hope this quick guide helped you fix your problem.

Thanks for reading.


❤️ You might like: