Tuple throwing unexpected TypeError error when holding list

The below code is throwing a TypeError.

my_list = [1,2]
my_tuple = (my_list,)
my_tuple[0] += [3,4]
print(my_tuple)

However when I simply put the result of indexing the tuple in a holder, it magically works.

my_list = [1,2]
my_tuple = (my_list,)
holder = my_tuple[0]
holder += [3,4]
print(my_tuple)

I feel like this shouldn’t be the case? Is this actually intentional?

It would work just the same if you did this:

my_tuple[0].extend([3, 4])

Does that make it look more reasonable now?

Thanks for the response! I’m still a little confused tho. If extend works why doesn’t the += work by default? Why do I have to put it in a holder to get the += to work?

When you do x += y, you’re asking the object x to do an augmented addition, and then whatever it gives back is assigned back to x. In the case of a tuple, assignment is illegal, but before that, the effect of += on a list has already happened - it’s the same as calling extend. These two are broadly equivalent:

my_tuple[0] += [3, 4]

_temp = my_tuple[0]
_temp.extend([3, 4])
my_tuple[0] = _temp

# Or if you prefer:
my_tuple[0] = my_tuple[0].__iadd__([3, 4])

Basically, a list’s += operator is “do an extend, then return self”, and the assignment still happens. (In contrast, an integer’s += operation is “return a new integer which is the sum of myself and the other”, with no change to the original object, so the assignment is everything.)

1 Like

The behaviour isn’t intentional in the sense that the confusing “exception even though the operation seemingly succeeded” is the goal. But it is intentional in the sense that we designed augmented assignments to be assignments, and assignments to a tuple item fail.

See the FAQ:

1 Like

There are many Q&As about this on Stack Overflow, for example python - a mutable type inside an immutable container - Stack Overflow.

1 Like