The TypeError: unhashable type: 'list'
usually occurs when you try to use a list object as a set element or dictionary key and Python internally passes the unhashable list into the hash()
function. But as lists are mutable objects, they do not have a fixed hash value. The easiest way to fix this error is to use a hashable tuple instead of a non-hashable list as a dictionary key or set element.
We’ll show how this is done in the remaining article. The last method is a unique way to still use lists in sets or dictionary keys that you likely won’t find anywhere else, so keep reading and learn something new! ๐
Problem Formulation and Explanation
๐ฌ Question: How to fix the TypeError: unhashable type: 'list'
in your Python script?
There are two common reasons for this error:
- You try to use a list as a dictionary key, or
- You try to use a list as a set element.
This is not a trivial problem because Python lists are mutable and, therefore, not hashable.
Here’s the first example:
my_list = [1, 2, 3] my_dict = {} my_dict[my_list] = 'hello Finxters!' ''' Traceback (most recent call last): File "C:\Users\xcent\Desktop\code.py", line 3, in <module> my_dict[my_list] = 'hello Finxters!' TypeError: unhashable type: 'list' '''
And here’s the second example:
my_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] my_set = set(my_list) ''' Traceback (most recent call last): File "C:\Users\xcent\Desktop\code.py", line 2, in <module> my_set = set(my_list) TypeError: unhashable type: 'list' '''
As you’ve seen in the previous two code snippets, the TypeError: unhashable type: 'list'
usually occurs when you try to use a list object as a set element or dictionary key.
But let’s dive deeper to find the real reason for the error:
๐ชฒ Minimal Reproducible Error Example: Lists are mutable objects so they do not have a fixed hash value. In fact, the error can be reproduced most easily when calling hash(lst)
on a list object lst
.
This is shown in the following minimal example that causes the error:
hash([1, 2, 3])
The output is the error message:
Traceback (most recent call last): File "C:\Users\xcent\Desktop\code.py", line 1, in <module> hash([1, 2, 3]) TypeError: unhashable type: 'list'
Because you cannot successfully pass a list into the hash()
function, you cannot directly use lists as set elements or dictionary keys.
But let’s dive into some solutions to this problem!
Method 1: Use Tuple Instead of List as Dictionary Key
The easiest way to fix the TypeError: unhashable type: 'list'
is to use a hashable tuple instead of a non-hashable list as a dictionary key. For example, whereas d[my_list]
will raise the error, you can simply use d[tuple(my_list)]
to fix the error.
Here’s an example of what you can do instead:
my_list = [1, 2, 3] my_dict = {} my_dict[tuple(my_list)] = 'hello Finxters!' print(my_dict) # {(1, 2, 3): 'hello Finxters!'}
The error may also occur when you try to use a list as a set element. Next, you’ll learn what to do in that case:
Method 2: Use Tuple Instead of List as Set Element
To fix the TypeError: unhashable type: 'list'
when trying to use a list as a set element is to use a hashable tuple instead of a non-hashable list. For example, whereas set.add([1, 2])
will raise the error, you can simply use set.add((1, 2))
or set.add(tuple([1, 2]))
to fix the error.
Here’s a minimal example:
my_set = set() # Error: my_set.add([1, 2]) # This is how to resolve the error: my_set.add((1, 2)) # Or: my_set.add(tuple([1, 2])) print(my_set) # {(1, 2)}
If you want to convert a list of lists to a set, you can check out my detailed tutorial on the Finxter blog:
๐ Related Tutorial: How to convert a list of lists to a set?
Method 3: Use String Representation of List as Set Element or Dict Key
To fix the TypeError: unhashable type: 'list'
, you can also use a string representation of the list obtained with str(my_list)
as a set element or dictionary key. Strings are hashable and immutable, so Python won’t raise the error when using this approach.
Here’s an example:
my_list = [1, 2, 3] # 1. Use str repr of list as dict key: d = {} d[str(my_list)] = 'hello Finxters' # 2. Use str repr of list as set element: s = set() s.add(str(my_list))
In both cases, we used the string representation of the list instead of the list itself. The string is immutable and hashable and it fixes the error.
But what if you really need a mutable set or dictionary key? Well, you shouldn’t but you can by using this approach:
Method 4: Create Hashable Wrapper List Class
You can still use a mutable list as a dictionary key, set element, or argument of the hash()
function by defining a wrapper class, say HackedList, that overrides the __hash__()
dunder method.
Pythonโs built-in hash(object)
function takes one object as an argument and returns its hash value as an integer. You can view this hash value as a unique fingerprint of this object.
The Python __hash__()
method implements the built-in hash()
function.
Here’s the minimal code example that creates a wrapper class HackedList that overrides the __hash__()
dunder method so you can use an instance of HackedList
as a dictionary key, set element, or just as input to the hash()
function:
my_list = [1, 2, 3] class HackedList: def __init__(self, lst): self.lst = lst def __hash__(self): return len(self.lst) my_hacked_list = HackedList(my_list) # 1. Pass hacked list into hash() function: print(hash(my_hacked_list)) # Output: 3 # 2. Use hacked list as dictionary key: d = dict() d[my_hacked_list] = 'hello Finxters' # 3: Use hacked list as set element: s = set() s.add(my_hacked_list)
Here’s the content of the dictionary and set defined previously:
{<__main__.HackedList object at 0x0000016CFB0BDFA0>: 'hello Finxters'} {<__main__.HackedList object at 0x0000016CFB0BDFA0>}
If you want to fix the ugly output, you can additionally define the __str__()
and __repr__()
magic methods like so:
my_list = [1, 2, 3] class HackedList: def __init__(self, lst): self.lst = lst def __hash__(self): return len(self.lst) def __str__(self): return str(self.lst) def __repr__(self): return str(self.lst) my_hacked_list = HackedList(my_list) # 1. Pass hacked list into hash() function: print(hash(my_hacked_list)) # Output: 3 # 2. Use hacked list as dictionary key: d = dict() d[my_hacked_list] = 'hello Finxters' # 3: Use hacked list as set element: s = set() s.add(my_hacked_list) print(d) print(s)
Beautiful output:
{[1, 2, 3]: 'hello Finxters'} {[1, 2, 3]}
Summary
The five most Pythonic ways to convert a list of lists to a set in Python are:
- Method 1: Use Tuple Instead of List as Dictionary Key
- Method 2: Use Tuple Instead of List as Set Element
- Method 3: Use String Representation of List as Set Element or Dict Key
- Method 4: Create Hashable Wrapper List Class
Feel free to check out more free tutorials and cheat sheets for learning and improving your Python skills in our free email academy: