Edit: (to resolve additional questions raised by your changes to the question):
a = a + b and a += b are not the same. The former runs a.__add__(b) , the latter runs a.__iadd__(b) ("add in-place").
The difference between the two is that the former always creates a new object (and renames the name a to this new object), while the latter changes the object in place (if it can and with a list can).
To illustrate this, simply look at the addresses of your objects:
>>> a = [1, 2] >>> id(a) 34660104 >>> a = a + [a] >>> id(a) 34657224 >>> id(a[2]) 34660104
"new" a was created from scratch, first taking values ββfrom the old list a , then concatenating the reference to the old object on it.
Compare this to:
>>> a = [1, 2] >>> id(a) 34658632 >>> a += [a] >>> id(a) 34658632 >>> id(a[2]) 34658632
(Old answer explaining circular references):
Consider this:
>>> a = [1, 2]; a += a >>> a [1, 2, 1, 2] >>> a = [1, 2]; a.extend(a) >>> a [1, 2, 1, 2] >>> a = [1, 2]; a += [a] >>> a [1, 2, [...]] >>> a = [1, 2]; a.append(a) >>> a [1, 2, [...]]
So, to summarize the first part:
For lists, a += a equivalent to calling a.extend(a) , which changes a in place by adding copies of the elements found in a at the beginning of this operation.
Conversely, a += [a] corresponds to a.append(a) , both of which create a link to the list a (that is, a pointer to its address in memory) and add this to the list. What is the so-called "circular link".
If you looked at the internal representation of a at this point, it would look something like this:
a: Reference to a list object at address 0xDEADBEEF a[0]: Reference to the integer object "1" a[1]: Reference to the integer object "2" a[2]: Reference to the same list object at address 0xDEADBEEF
Older versions of Python (before 1.5.1) were not smart enough to detect this, so if you need to print a , you will get [1, 2, [1, 2, [1, 2, [1, 2, [1, 2, [1, 2, ... etc. in an infinite loop. Starting with Python 1.5.1, the interpreter detects this, instead print [1, 2, [...]] .