Lesson 14
Hashability Rules and Collection Conversions
Learn which Python objects can become dictionary keys or set elements, fix TypeError unhashable type, and master conversions between list, tuple, set, and dict.
What you will learn
Hashability rules · Nesting validity · Collection conversions · Fixing TypeError: unhashable type
Learn which Python objects can become dictionary keys or set elements, fix TypeError: unhashable type, and master conversions between list, tuple, set, and dict.
| Topic | Why it matters |
|---|---|
| Hashable vs unhashable | Dict keys and set members |
| Nesting rules | Avoid runtime TypeError |
| Conversions | Deduplicate, sort, rebuild |
| Fixes | Interview and production debugging |
After File 13 — Nested Dictionaries, you have seen combination patterns in practice. This lesson explains the underlying rule — hashability — and the conversion toolkit you will use everywhere.
Related: Mutable vs Immutable · Identity operators.
Learning roadmap
What is hashability?
A hashable object has a stable hash value throughout its lifetime. Python uses that hash to store objects efficiently inside sets and as dictionary keys.
Golden rule
| Can be dict key or set element | Cannot be dict key or set element |
|---|---|
int, float, str, bool |
list |
tuple (hashable contents only) |
dict |
frozenset |
set (mutable) |
Memory hook: If it can change after creation, it usually cannot be hashed.
1. Nesting rules (interview table)
| Inner → Outer | Allowed? |
|---|---|
| List → List | Yes |
| Dict → Tuple | Yes |
| List → Set | No |
| Dict → Set | No |
| Tuple → Set | Only if all elements hashable |
Examples
Valid:
valid = {(1, 2), (3, 4)}
valid_set = {frozenset({1, 2}), frozenset({3, 4})}Invalid:
bad = {[1, 2]} # TypeError: unhashable type: 'list'
bad = {{1: 2}} # TypeError: unhashable type: 'dict'Full combination matrix: File 13 — Nested Dictionaries.
2. Mutable inside immutable
This is one of the most misunderstood Python concepts.
The tuple is immutable, but the list inside it is still mutable.
t = (10, [1, 2, 3])
t[1].append(4)
print(t)
# (10, [1, 2, 3, 4])Key insight: Immutability applies only to the outer container, not automatically to nested objects.
Same idea for a dict inside a tuple or list — the outer shell may be fixed, but the inner dict can still change.
record = (100, {"x": 1})
record[1]["y"] = 2 # OK — mutating inner dictBut remember: a tuple containing a dict is not hashable, so it cannot go inside a set.
3. Collection conversion cheat sheet
These conversions appear constantly in interviews and production code.
| From | To | Code |
|---|---|---|
| List | Tuple | tuple(lst) |
| Tuple | List | list(t) |
| List | Set | set(lst) |
| Set | List | list(s) |
| String | List | list(text) |
| String | Set | set(text) |
| Pairs | Dict | dict(zip(keys, values)) |
Example: list → tuple
lst = [1, 2, 3]
t = tuple(lst)
print(t)
# (1, 2, 3)Example: list → set (deduplication)
marks = [85, 90, 85, 78]
unique = set(marks)
print(unique)
# {90, 85, 78} — order variesPreserve order while deduplicating:
words = ["apple", "banana", "apple"]
print(list(dict.fromkeys(words))) # ['apple', 'banana']4. Dictionary conversions
Keys, values, and items as lists
d = {"a": 10, "b": 20}
print(list(d.keys()))
print(list(d.values()))
print(list(d.items()))Output:
['a', 'b']
[10, 20]
[('a', 10), ('b', 20)]Build a dictionary from two lists
keys = ["id", "name"]
values = [101, "RS"]
student = dict(zip(keys, values))
print(student)
# {'id': 101, 'name': 'RS'}5. Deduplicate → sort → rebuild pipeline
This is an interview favorite.
Remove duplicates → sort → create immutable tuple.
data = (10, 5, 10, 3, 5)
result = tuple(sorted(set(data)))
print(result)
# (3, 5, 10)Why this works:
set()removes duplicatessorted()returns a sorted listtuple()converts it into an immutable sequence
One-liner for a list:
marks = [85, 90, 85, 78, 90]
print(tuple(sorted(set(marks))))6. Fixing "unhashable type" errors
Most common Python collection error:
TypeError: unhashable type: 'list'Wrong
my_set = {[1, 2]}
# TypeErrorCorrect
my_set = {(1, 2)}
print(my_set)
# {(1, 2)}Another common mistake
Wrong:
cache = {{1: 2}: "value"} # TypeErrorCorrect:
cache = {("x", "y"): "value"}
cache = {frozenset({"read"}): "viewer"}Reason: Dictionary keys must always be hashable.
| Error context | Fix |
|---|---|
| List in set | Use tuple(lst) if elements are hashable |
| Dict in set | Not allowed — use list of dicts or frozenset of keys |
| Dict as key | Use str, int, tuple, or frozenset |
Mini project — role permission cache
Use tuples and frozensets as hashable keys.
valid = {
(1, 2),
frozenset({"read"})
}
permissions = {
("read", "write"): "admin",
("read",): "viewer"
}
print(valid)
print(permissions[("read", "write")])Output:
{(1, 2), frozenset({'read'})}
adminInterview summary
| Concept | Remember |
|---|---|
| Hashable | Can be dict key or set element |
| Unhashable | Mutable containers (list, dict, set) |
| Tuple | Hashable only if contents are hashable |
| Frozenset | Immutable + hashable |
| Deduplication | set(list) |
| Sorted unique tuple | tuple(sorted(set(data))) |
| Pairs → dict | dict(zip(keys, values)) |
Common interview mistakes
Mistake 1 — using a list as a set element:
# TypeError
# s = {[1, 2]}
s = {(1, 2)}Mistake 2 — assuming all tuples are hashable:
# TypeError — list inside tuple
# hash((1, [2, 3]))
hash((1, 2, 3)) # OKMistake 3 — forgetting set loses order:
# Need sorted unique list, not just set
sorted(set([3, 1, 2, 1])) # [1, 2, 3]
tuple(sorted(set([3, 1, 2, 1]))) # (1, 2, 3)Mistake 4 — confusing outer immutability with inner mutability:
t = (10, [1, 2])
t[1].append(3) # works — list inside is mutable
# t[0] = 99 # TypeError — tuple shell is fixedPractice questions
Test yourself before File 15 — Practice Programs:
- Why is
{[1, 2]}invalid? - Convert
[1, 2, 2, 3]into a sorted unique tuple. - Can a tuple containing a list be a set element?
- How do you build a dict from two parallel lists?
- What is the fix for
TypeError: unhashable type: 'dict'as a key?
Knowledge check
Q1: Why is {[1, 2]} invalid?
Answer: Lists are mutable and unhashable — they cannot be set elements.
Q2: Convert [1, 2, 2, 3] into a sorted unique tuple?
Answer: tuple(sorted(set([1, 2, 2, 3]))) → (1, 2, 3).
Q3: Can a tuple containing a list be a set element?
Answer: No — the inner list makes the tuple unhashable.
Q4: Build dict from keys = ["a","b"], values = [1, 2]?
Answer: dict(zip(keys, values)).
Q5: Dict as dictionary key — allowed?
Answer: No — use tuple, frozenset, str, or int instead.
Key takeaways
- Hashable = stable hash → valid dict key or set element.
- Mutable containers (
list,dict,set) are unhashable. - Tuple is hashable only when every element inside is hashable.
- Convert with
tuple(),list(),set(), anddict(zip(...)). - Pipeline:
tuple(sorted(set(data)))for sorted unique immutable results.
Loading playground…