Recent chats
ASKGEEZ Q&A GUIDETechnology & devices

Why can a tuple be changed indirectly even though tuples are immutable?

Quick answer

A tuple’s items cannot be reassigned, but an item can refer to a mutable object, such as a list. You can change that list without replacing the tuple item. For example, t = ([1, 2],) followed by t[0].append(3) changes the list’s contents, while the tuple still refers to that list. By contrast, t[0] = [4] attempts to replace the tuple item and is not allowed. [S1]

LET’S WORK THROUGH IT

The question, the details, the next step.

Question

I thought tuples were immutable. Why does this change the value I see? I have t = ([1, 2],) and then t[0].append(3). Does that mean the tuple itself changed?

Geez

The list changed, not the tuple’s item. The tuple still has one item referring to the same list; that list’s contents are now different. A tuple can contain a mutable object such as a list, even though you cannot reassign the tuple’s items. [S1]

t = ([1, 2],)
print(t)       # ([1, 2],)
t[0].append(3)
print(t)       # ([1, 2, 3],)

The display shows the list’s updated contents. The trailing comma makes ([1, 2],) a one-item tuple, and the square brackets make its item a list.

Follow-up question

So what would count as changing the tuple itself? What if I try t[0] = [4] instead?

Geez

That assignment tries to put a different list in tuple position 0. Tuple items cannot be reassigned, so t[0] = [4] is not allowed. [S1]

t[0].append(3)  # Mutates the list inside the tuple
t[0] = [4]       # Tries to replace a tuple item; not allowed

The key distinction is whether the operation changes the object already in the tuple or tries to replace the tuple’s reference to that object. The first works here because the contained list is mutable; the second conflicts with tuple immutability. [S1]

Follow-up question

How can I check this in my own code without getting confused by the printed tuple?

Geez

Look at the operation applied to the item. A method such as .append() acts on the list that the item refers to. An assignment such as t[0] = ... tries to replace the item. You can inspect the list’s contents before and after the method call:

t = ([1, 2],)
print("before:", t[0])
t[0].append(3)
print("after: ", t[0])

This shows the list changing. It does not show the tuple item being replaced. The example illustrates a tuple containing a list; it does not mean that every object inside a tuple is mutable.

Follow-up question

Can you give me a compact checklist for reviewing a tuple that seems to change?

Geez

Ask yourself:

  1. What object does the tuple position refer to?
  2. Does the operation mutate that object, or try to assign a new item to the tuple?
  3. Is the output showing updated contents of an object that was already inside the tuple?

For this example, position 0 refers to a list. Calling t[0].append(3) changes that list’s contents, while the tuple’s item remains in place. [S1]

A practical checklist

  • Identify the object held at the tuple position that appears to change.

  • Check whether the operation mutates that object or tries to assign a new tuple item.

  • Compare the contained object’s contents before and after the operation.

  • Remember that printing a tuple can show updated contents of a mutable object it contains.

A few more useful answers

Does `t[0].append(3)` replace the first tuple item?

No. It changes the list referred to by the first item; it does not assign a different item to that tuple position. [S1]

Why does printing the tuple show the new list contents?

The tuple still refers to the list, and the display shows the list’s current contents.

Can I assign a new list with `t[0] = [4]`?

No. That attempts to reassign a tuple item, which is not allowed. [S1]

Sources

References used for this guide.

  1. [S1] Python Tutorial: Tuples and sequences
    docs.python.org · Checked

YOUR QUESTION. YOUR DETAILS.

Let’s work through your situation.

Get a tailored answer or help with your next task. Starts at $1, with a quote before you pay.

Ask your own question
← Back to Geez at Work