How to overcome TypeError: unhashable type: 'list'
Categories:
Overcoming TypeError: unhashable type: 'list' in Python

Learn why Python raises 'TypeError: unhashable type: 'list'' when using lists as dictionary keys or set elements, and discover effective solutions.
The TypeError: unhashable type: 'list'
is a common error encountered by Python developers, especially when working with dictionaries and sets. This error occurs because lists are mutable, meaning their contents can be changed after creation. Python requires dictionary keys and set elements to be hashable â immutable objects that have a consistent hash value throughout their lifetime. This article will explain the concept of hashability, why lists are unhashable, and provide practical solutions to resolve this TypeError
.
Understanding Hashability and Immutability
In Python, hashable objects have a hash value that never changes during their lifetime. This hash value is used internally by data structures like dictionaries and sets for efficient storage and retrieval. Immutable objects (like numbers, strings, and tuples) are hashable because their value cannot change. Mutable objects (like lists, dictionaries, and sets) are unhashable because their content can be modified, which would change their hash value and break the integrity of hash-based data structures.
flowchart TD A["Object Type"] --> B{"Is it Mutable?"} B -->|Yes| C["Unhashable (e.g., list, dict, set)"] B -->|No| D["Immutable (e.g., int, str, tuple)"] C --> E["Cannot be dict key or set element"] D --> F["Hashable"] F --> G["Can be dict key or set element"] style C fill:#f9f,stroke:#333,stroke-width:2px style E fill:#f9f,stroke:#333,stroke-width:2px
Decision flow for object hashability in Python
Common Scenarios Leading to the Error
This TypeError
typically arises in two main situations: when attempting to use a list as a key in a dictionary, or when trying to add a list as an element to a set. Both dictionaries and sets rely on the hash values of their keys/elements for quick lookups and to ensure uniqueness. Since a list's content can change, its hash value would also change, making it unsuitable for these purposes.
# Scenario 1: Using a list as a dictionary key
my_list = [1, 2, 3]
my_dict = {}
try:
my_dict[my_list] = "some_value"
except TypeError as e:
print(f"Caught expected error: {e}")
# Scenario 2: Adding a list to a set
my_set = set()
try:
my_set.add(my_list)
except TypeError as e:
print(f"Caught expected error: {e}")
Examples demonstrating 'TypeError: unhashable type: 'list''
Solutions to the 'unhashable type: 'list'' Error
To resolve this error, you need to replace the unhashable list with a hashable alternative that represents the same data. The most common and Pythonic solution is to convert the list into a tuple.
Solution 1: Convert List to Tuple
Tuples are immutable sequences, making them hashable. By converting your list to a tuple, you can use it as a dictionary key or a set element. This is the most straightforward and frequently used solution.
# Using a tuple as a dictionary key
my_list = [1, 2, 3]
my_tuple = tuple(my_list)
my_dict = {my_tuple: "some_value"}
print(f"Dictionary with tuple key: {my_dict}")
# Using a tuple as a set element
my_set = set()
my_set.add(my_tuple)
print(f"Set with tuple element: {my_set}")
# Example with nested lists (convert inner lists to tuples too)
nested_list = [1, [2, 3], 4]
nested_tuple = tuple(item if not isinstance(item, list) else tuple(item) for item in nested_list)
my_dict[nested_tuple] = "nested_value"
print(f"Dictionary with nested tuple key: {my_dict}")
Converting lists to tuples to make them hashable
Solution 2: Use a String Representation (Less Common)
If the exact list structure isn't critical but you need a unique identifier, you could convert the list to a string. This is generally less efficient and less Pythonic than using tuples, but it can be an option for simple cases or when you need a human-readable key.
my_list = ['apple', 'banana', 'cherry']
string_key = str(my_list) # Or a more controlled serialization like json.dumps()
my_dict = {string_key: "fruits"}
print(f"Dictionary with string key: {my_dict}")
my_set = set()
my_set.add(string_key)
print(f"Set with string element: {my_set}")
Using string representation of a list as a key/element
str([1, 2])
is different from str([2, 1])
, even if logically they represent the same collection of items. For such cases, sort the list before converting to a string or tuple.Solution 3: Custom Class with __hash__
and __eq__
(Advanced)
For more complex scenarios where you need custom logic for hashability (e.g., only certain attributes of an object should contribute to its hash), you can define a custom class and implement the __hash__
and __eq__
methods. This allows you to control how instances of your class are hashed and compared for equality.
class MyData:
def __init__(self, id, values):
self.id = id
# Store values as a tuple to ensure hashability of the internal state
self.values = tuple(values)
def __hash__(self):
# Hash based on id and the tuple of values
return hash((self.id, self.values))
def __eq__(self, other):
if not isinstance(other, MyData):
return NotImplemented
return self.id == other.id and self.values == other.values
def __repr__(self):
return f"MyData(id={self.id}, values={list(self.values)})"
# Now MyData objects can be used as dictionary keys or set elements
data1 = MyData(1, [10, 20])
data2 = MyData(2, [30, 40])
data3 = MyData(1, [10, 20]) # Logically equal to data1
my_dict = {data1: "first entry"}
print(f"Dictionary with custom object key: {my_dict}")
my_set = set()
my_set.add(data1)
my_set.add(data2)
my_set.add(data3) # This will not add a duplicate because data3 == data1
print(f"Set with custom object elements: {my_set}")
Implementing __hash__
and __eq__
for custom hashable objects
__hash__
, it's crucial to also implement __eq__
. If two objects are considered equal (__eq__
returns True
), their hash values must be the same. If __eq__
is implemented but __hash__
is not, Python will automatically make the object unhashable.