Tuples and immutability

Chris Angelico rosuav at gmail.com
Thu Feb 27 11:14:08 EST 2014


On Fri, Feb 28, 2014 at 3:01 AM, Eric Jacoboni <eric.jacoboni at gmail.com> wrote:
> I'm using Python 3.3 and i have a problem for which i've still not found
> any reasonable explanation...
>
>>>> a_tuple = ("spam", [10, 30], "eggs")
>>>> a_tuple[1] += [20]
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> TypeError: 'tuple' object does not support item assignment
>
> Ok... I accept this message as += is a reassignment of a_tuple[1] and a
> tuple is immutable...
>
> But, then, why a_tuple is still modified?
>
>>>> a_tuple
> ('spam', [10, 30, 20], 'eggs')
>
> I get a TypeError for an illegal operation, but this operation is still
> completed?

This is a common confusion.

The += operator does two things. First, it asks the target to please
do an in-place addition of the other operand. Then, it takes whatever
result the target gives back, and assigns it back into the target. So
with a list, it goes like this:

>>> foo = [10, 30]
>>> foo.__iadd__([20])
[10, 30, 20]
>>> foo = _

Note that the second step returned a three-element list. Then the +=
operator stuffs that back into the source. In the case of a list, it
does that addition by extending the list, and then returning itself.

The putting-back-into-the-target step fails with a tuple, because a
tuple's members can't be reassigned. But the list has already been
changed by that point. So, when you go to look at it, you see a
changed list.

You can call on this behaviour more safely by using the append() or
extend() methods.

>>> a_tuple = ("spam", [10, 30], "eggs")
>>> a_tuple[1].extend([20])
>>> a_tuple
('spam', [10, 30, 20], 'eggs')

>>> a_tuple = ("spam", [10, 30], "eggs")
>>> a_tuple[1].append(20)
>>> a_tuple
('spam', [10, 30, 20], 'eggs')

(append will add one more element, extend is roughly the same as you
had). Then you're not trying to assign to the tuple, but you're still
mutating the list.

Hope that helps!

ChrisA



More information about the Python-list mailing list