Python Programming problem - Lists and +=

I’m learning about Python (version 2.4.2 if that makes any differences), but I’ve come across something that doesn’t seem to do what I want it to do.

I gather that a += b, for example, is the equivalent of a = a + b. This seems to work for numbers, thus:

>>> a = 3
>>> a += 2
>>> print a
>>> 5

However, it seems to do odd things when you have lists of lists. For example:

>>> a = [[9]]*10
>>> print a
[[9], [9], [9], [9], [9], [9], [9], [9], [9], [9]]
>>> a[5] += [3]
>>> print a
[[9, 3], [9, 3], [9, 3], [9, 3], [9, 3], [9, 3], [9, 3], [9, 3], [9, 3], [9, 3]]
>>>

What I would expect a[5] += [3] to do is append 3 to the 6th entry in a, to make a[5] = [9.3], and the other entries equal to [9]. However, it appears here to append it to all the lists in a.

Is this just a quirk in Python, or something I’m doing wrong? Can I use += in this way to do what I want, and/or is there another (better) way of doing it?

To clarify, what I want to do sometimes involves appending more than one element to lists, such as appending 3 and 4, to get [9,3,4].

I happened to have #python open on freenode, so I passed your question along. Hope this helps:


me: how does the += operator work on lists? why does my second statement here add an indice with the number three to each field?
me: a = [[9]]*10;a[5] += [3];print a
notme: += is the .extend method.
notme: but, [[9]] * 10 will create a list with 10 references to the same sublist ( [9] )
notme: __iadd__ = extend ...
notme: when you do [[9]] * 10, you're repeating the same reference, it's the same list
notme: use something like [[9] for i in xrange(10)]


a = [x] * 9 creates a list with 10 references to x. And a[y] = z modifies whatever a[y] points to (not a[y] itself), which would be the same thing that all the other elements of list a point to.

Thanks for the help. I think I get what’s happening. I’ve had a bit more of a look, and other methods applied to a[5] are the same. (e.g. a[5].sort() sorts all members of a, or rather sorts the one list they are all pointing to, and similar applies to extend(), which I gather from alterego is what += actually uses for lists.

Will all list methods treat [[9]]*10 (and smilar), in this way?

Also, a[5] = a[5] + [2] only affects a[5] as I would expect. Do I take it if I use a[5] = a[5] + x, then that creates a seperate “slot”, for a[5] to point to, seperate from the other members of a?

In any case, the a = a + x method seems to do what I want it to do in the program I’m writing at the moment, so I’ll probably probably leave it at that for this program.

Thanks for the help. I think I get what’s happening. I’ve had a bit more of a look, and other methods applied to a[5] are the same. (e.g. a[5].sort() sorts all members of a, or rather sorts the one list they are all pointing to, and similar applies to extend(), which I gather from alterego is what += actually uses for lists.

Will all list methods treat [[9]]*10 (and smilar), in this way?

Also, a[5] = a[5] + [2] only affects a[5] as I would expect. Do I take it if I use a[5] = a[5] + x, then that creates a seperate “slot”, for a[5] to point to, seperate from the other members of a?

In any case, the a = a + x method seems to do what I want it to do in the program I’m writing at the moment, so I’ll probably probably leave it at that for this program.

It’s not so much a quirk of lists, it’s more that there is a fundamental difference between the assignment operator ‘=’ and “augmented” operators like ‘+=’.

The ‘=’ operator always creates a new reference, while ‘+=’ never does. So in your example, a[5] = a[5] + [2] makes a[5] point to an entirely new list of the form [[9], [2]], whereas a[5] += [2] doesn’t change the reference a[5] itself, it changes whatever it points to (in this case, the list [9] that all the other members of a happen to point to).

I think I understand now. += acts in a similar way for other data types (integers, strings, etc), as for lists, it’s just that it’s only when you create multiple elements pointing to the same thing, as with [[9]]*10, that you actually notice it.

What about other methods, such as x.sort()?
Do they act on whatever x points to, rather than create a new reference (as a = a
+b does)?