Baltic Sun Baltic Sun - 1 year ago 62
Python Question

Updating a list within a tuple

I was just toying around in the interpreter and ran across something that I do not understand. When I create a tuple with a list as one the elements and then try to update that list, something strange happens. For example, when I run this:

tup = (1,2,3,[4,5])
tup[3] += [6]

I get:

TypeError: 'tuple' object does not support item assignment

Which is exactly what I expected. However then when I reference the tuple again, I get:

>>> tup
(1, 2, 3, [4, 5, 6])

So the list was in fact updated even though python threw an exception. How does that work? I can't imagine a scenario where I would actually want to do something like this, but I still would like to understand what is going on. Thank you.

Answer Source

This is actually documented in the Python docs.

EDIT: Here's a summary so that this is a more complete answer.

  1. When we use +=, Python calls the __iadd__ magic method on the item, then uses the return value in the subsequent item assignment.
  2. For lists, __iadd__ is equivalent to calling extend on the list and then returning the list.
  3. Therefore, when we call tup[3] += [6], it is equivalent to:

    result = tup[3].__iadd__([6])
    tup[3] = result
  4. From #2, we can determine this is equivalent to:

    result = tup[3].extend([6])
    tup[3] = result
  5. The first line succeeds in calling extend on the list, and since the list is mutable, it updates. However, the subsequent assignment fails because tuples are immutable, and throws the error.