Skip to content
TaeyoungKim.dev

Why a List Inside an Immutable Python Tuple Can Still Change

PythonWritten 3 min readTaeyoungKim
LinkedInX

You put configuration data in a tuple to prevent changes, yet a new item appears in the task list inside it. If tuples are immutable, how did the list change? The distinction is between a slot in the tuple and the list object that slot references.

Why does assigning a tuple item raise TypeError?

After a tuple is created, you cannot assign a different object to one of its item positions. Here, record[0] refers to the list named steps:

python
steps = ["draft"]
record = (steps, "open")

record[0] = ["reviewed"]  # TypeError: 'tuple' object does not support item assignment

Replacing the slot itself with a new list fails. record[1] = "closed" would fail for the same reason. This is the scope of the tuple's immutability.

Why can you append to the list inside it?

Omit the failed assignment and start again with the same steps and record values:

The tuple's reference to the list remains in place. append() changes the list's contents, whereas assigning a new list to record[0] attempts to replace a tuple item.

python
steps = ["draft"]
record = (steps, "open")

record[0].append("reviewed")
print(record)             # (['draft', 'reviewed'], 'open')
print(record[0] is steps) # True

record[0] still points to the same list. The list's contents changed, so printing the tuple now looks different even though its items were not reassigned. Calling steps.append() outside the tuple would produce the same visible change because both names reach that list.

Avoid assuming that record[0] += ["approved"] is safe. The in-place operation can append to the list before Python tries to assign the result back into the tuple and raises TypeError. An exception does not mean the list stayed unchanged; the Korean source verified both effects in a separate run.

Does wrapping a list in a tuple freeze the list?

No. A tuple around a list does not make the inner list immutable. If you need a fixed record of its current values, convert the inner list too:

python
steps = ["draft"]
record = (steps, "open")
snapshot = (tuple(steps), "open")

steps.append("reviewed")
print(record)   # (['draft', 'reviewed'], 'open')
print(snapshot) # (('draft',), 'open')

snapshot holds a separate tuple of strings as they were at that moment. If an inner item is itself mutable, one tuple() conversion will not freeze every nested object. Decide how deeply the values must remain unchanged.

What about a dictionary key?

A tuple containing a list is unhashable, so it cannot serve as a dictionary key. Being a tuple on the outside is insufficient. A key such as snapshot needs hashable contents all the way down. If later changes to a shared list must not change an earlier record, preserving the values at that moment matters even before you consider using them as a key.

Key takeaways

Tuple immutability prevents reassigning its item positions; it does not freeze a mutable object referenced there. record[0] = ... fails, while record[0].append(...) changes the existing list. For an unchanging record, inspect and copy or convert mutable inner values as needed.

Author

TaeyoungKim

Connecting technical foundations with implementation, verification, and production decisions.

#Python tuple#tuple immutability#Python list#append#TypeError

Read next