✋ Update: This post was originally published on my blog decodingweb.dev, where you can read the latest version 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, 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:
#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:
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:
- TypeError: missing 1 required positional argument: 'self' (Fixed)
- Unindent does not match any outer indentation level error in Python (Fixed)
- AttributeError module 'DateTime' has no attribute 'strptime' (Fixed)
- AttributeError: 'str' object has no attribute 'decode' (Fixed)
- How back-end web frameworks work?
Top comments (0)