# Tuples and immutability

Oscar Benjamin oscar.j.benjamin at gmail.com
Sat Mar 1 19:55:53 CET 2014

```On 27 February 2014 21:47, Nick Timkovich <prometheus235 at gmail.com> wrote:
> On Thu, Feb 27, 2014 at 10:33 AM, Chris Angelico <rosuav at gmail.com> wrote:
>>
>> It's unintuitive, but it's a consequence of the way += is defined. If
>> you don't want assignment, don't use assignment :)
>
> Where is `.__iadd__()` called outside of `list += X`?

Numpy uses it for in-place operations with numpy arrays:

>>> import numpy
>>> a = numpy.arange(10)
>>> a
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> a[::2] += 10
>>> a
array([10,  1, 12,  3, 14,  5, 16,  7, 18,  9])

It makes sense for any mutable type that supports +. The stdlib
doesn't have many of these. The obvious one is list but there's also
MutableString (in 2.x):

>>> from UserString import MutableString
>>> a = MutableString("qwe")
>>> a
'qwe'
>>> b = a
>>> b += "asd"
>>> a
'qweasd'

> If the only difference from `.extend()` is that it returns `self`, but the list was
> already modified anyway, why bother with reassignment?

I don't know of any situation where __iadd__ is defined but doesn't
return self and I can't think of a use case apart from operator abuse.

I had thought that the other difference was that .extend would accept
any iterable but it seems += does also. Perhaps that was changed at
some point.

>>> l = [1, 2, 3]
>>> l + (1, 2, 3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "tuple") to list
>>> l += (1, 2, 3)
>>> l
[1, 2, 3, 1, 2, 3]

Oscar

```