How to resolve TypeError when using lists as dictionary keys in Python
Problem
When I tried to use a list as a dictionary key in Python, I got this error:
>>> coords = {[1, 2]: "value"}Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: unhashable type: 'list'I wanted to store coordinate pairs as dictionary keys for a game board I was building. The error made no sense to me at first—why can’t I use a list as a key when tuples work fine?
What happened?
I was building a simple chess game and needed to track which piece was at each position. My first attempt looked like this:
# My initial approach - using lists as keysboard = { [0, 0]: "white_rook", [0, 1]: "white_knight", [0, 2]: "white_bishop"}When I ran this code, Python immediately threw the TypeError: unhashable type: 'list' error.
I thought maybe I was doing something wrong with the syntax, so I tried adding keys one at a time:
board = {}position = [0, 0]board[position] = "white_rook" # Same errorStill the same error. Then I remembered seeing tuples used as dictionary keys in some code examples, so I tried that:
# Using tuples insteadboard = { (0, 0): "white_rook", (0, 1): "white_knight", (0, 2): "white_bishop"}
# Access works perfectlypiece = board[(0, 1)] # Returns "white_knight"This worked! But I didn’t understand why tuples work when lists don’t. Aren’t they both just sequences?
The reason
I think the key reason for this error comes down to how Python dictionaries work internally.
Dictionaries use hash tables for fast lookups. When you add a key-value pair, Python:
- Calculates a hash value from the key
- Stores the value at that hash location
- Uses the hash to quickly find the value later
For this to work, the key’s hash value must never change. If the hash changes, Python won’t be able to find the value anymore.
Here’s the crucial difference:
- Lists are mutable - you can modify them after creation
- Tuples are immutable - once created, they cannot change
# Lists can changemy_list = [1, 2]my_list[0] = 5 # This worksmy_list.append(3) # This also works
# Tuples cannot changemy_tuple = (1, 2)my_tuple[0] = 5 # TypeError: 'tuple' object does not support item assignmentIf Python allowed lists as dictionary keys and you modified a list that was being used as a key, its hash would change. Then the dictionary wouldn’t be able to find that key anymore—it would be looking in the wrong hash bucket.
Python prevents this entire problem by making lists unhashable. Tuples don’t have this problem because they can’t be modified, so their hash value stays the same forever.
What I learned about hashability
Through researching this error, I learned that an object is hashable in Python if:
- It has a
__hash__()method that returns an integer - It has an
__eq__()method for comparison - The hash value never changes during the object’s lifetime
- Objects that compare equal have the same hash value
I wrote a simple function to check if an object is hashable:
def is_hashable(obj): try: hash(obj) return True except TypeError: return False
print(is_hashable((1, 2, 3))) # Trueprint(is_hashable([1, 2, 3])) # Falseprint(is_hashable({1, 2, 3})) # False (sets are mutable)print(is_hashable("hello")) # True (strings are immutable)This helped me understand what can and cannot be used as dictionary keys.
Common pitfalls I discovered
While working through this, I found two other ways to trigger the same error:
First pitfall: Using tuples that contain mutable elements
# This looks like a tuple, but it contains a listkey = (1, 2, [3, 4])board = {key: "value"}# TypeError: unhashable type: 'list'
# Even though the outer structure is a tuple,# the list inside makes the whole thing unhashableSecond pitfall: Forgetting that nested structures must also be immutable
# This works - all elements are immutablegood_key = (1, 2, (3, 4))board = {good_key: "value"}
# This doesn't work - contains a listbad_key = (1, 2, [3, 4])board = {bad_key: "value"} # TypeErrorThe rule is: a tuple is only hashable if ALL its elements are hashable.
Practical examples where I use tuple keys
Now that I understand this, I use tuple keys in several situations:
1. Coordinate systems
# Grid or board positionsgrid_values = { (0, 0): "start", (5, 5): "end", (2, 3): "obstacle"}
# 3D coordinatesspace = { (10, 20, 30): "point_a", (40, 50, 60): "point_b"}2. Composite keys
# Student grades by (student_id, semester)grades = { (101, "Fall 2024"): {"math": 95, "english": 88}, (101, "Spring 2025"): {"math": 92, "english": 91}}
# Cache keys combining multiple parameterscache = {}def expensive_operation(x, y, mode): key = (x, y, mode) if key not in cache: cache[key] = compute(x, y, mode) return cache[key]3. State representation
# Game state as (position, direction)states = { ((0, 0), "north"): "standing", ((0, 0), "east"): "turning"}Why not use strings instead?
I initially thought about just converting my coordinates to strings like “0,0” instead of using tuples. But I found that tuples are better because:
- Type safety - integers stay as integers, not strings
- No parsing needed - direct access without splitting strings
- Faster - no string operations required
- Less error-prone - can’t have malformed strings like “0, 2” vs “0,2”
# String approach (what I considered)string_coords = {"0,0": "value"}piece = string_coords["0,0"] # Workspiece = string_coords["0, 0"] # KeyError! Extra space breaks it
# Tuple approach (what I use)tuple_coords = {(0, 0): "value"}piece = tuple_coords[(0, 0)] # Always worksSummary
In this post, I showed how I resolved the TypeError: unhashable type: 'list' error by switching from lists to tuples when using dictionary keys. The key point is that dictionary keys must be hashable (immutable), so tuples work but lists don’t.
I also learned that:
- All elements within a tuple must be immutable for the tuple to be hashable
- Tuples are ideal for composite keys like coordinates and multi-dimensional data
- Tuples are better than string concatenation for composite keys due to type safety and performance
The error that confused me at first now makes complete sense—it’s Python protecting the integrity of dictionary lookups by ensuring key hashes can never change.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 Python documentation on hashability
- 👨💻 Why dictionaries require immutable keys
- 👨💻 Python tuple vs list comparison
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments