About "TypeError: unhashable type: ‘dict'” in Python
Tags: python, programming
Published: 2023-02-04 14:31:46

> ✋ **Update:** This post was originally published on my blog [decodingweb.dev](https://www.decodingweb.dev), where you can read the [latest version](https://www.decodingweb.dev/python-typeerror-unhashable-type-dict-fixed) for a 💯 user experience. _~reza_

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

Whether you’re [learning to code](https://www.decodingweb.dev/learn-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](https://docs.python.org/3/glossary.html#term-hashable):

> 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:

| #1 | Most of Python’s immutable built-in objects (strings, numeric values, etc.) are hashable.           |
|----|-----------------------------------------------------------------------------------------------------|
| #2 | Immutable objects (such as tuples and frozensets) are only hashable if their elements are hashable. |
| #3 | Mutable 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:

```python
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?

```python
# 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:

```python
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:**

- [TypeError: missing 1 required positional argument: 'self' (Fixed)](https://www.decodingweb.dev/python-typeerror-missing-1-required-positional-argument-self)
- [Unindent does not match any outer indentation level error in Python (Fixed)](https://www.decodingweb.dev/python-indentationerror-unindent-does-not-match-any-outer-indentation-level-fix)
- [AttributeError module 'DateTime' has no attribute 'strptime' (Fixed)](https://www.decodingweb.dev/attributeerror-module-datetime-has-no-attribute-strptime-python)
- [AttributeError: 'str' object has no attribute 'decode' (Fixed)](https://www.decodingweb.dev/python-attributeerror-str-object-has-no-attribute-decode-fix)
- [How back-end web frameworks work?](https://www.decodingweb.dev/backend-web-frameworks)