Ellipsis lists [...] and concatenating a list to itself [duplicate]
Solution 1:
Edit: (to address the additional issues raised by your edits to the question):
a = a + b
and a += b
are not the same operation. The former executes a.__add__(b)
, the latter executes a.__iadd__(b)
("in-place add").
The difference between the two is that the former always creates a new object (and rebinds the name a
to that new object) while the latter modifies the object in-place (if it can, and with a list, it can).
To illustrate this, just look at the addresses of your objects:
>>> a = [1, 2]
>>> id(a)
34660104
>>> a = a + [a]
>>> id(a)
34657224
>>> id(a[2])
34660104
The "new" a
was constructed from scratch, first taking the values from the old list a
, then concatenating the reference to the old object to it.
Contrast this to:
>>> a = [1, 2]
>>> id(a)
34658632
>>> a += [a]
>>> id(a)
34658632
>>> id(a[2])
34658632
(Old answer, explaining cyclic 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
is equivalent to calling a.extend(a)
which modifies a
in-place, adding copies of the elements found in a
at the start of this operation.
Conversely, a += [a]
corresponds to a.append(a)
, both of which create a reference to the list a
(i. e. a pointer to its address in memory) and add that to the list. Which constitutes a so-called "cyclic reference".
If you were to look at the internal representation of a
at that 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
Old Python versions (pre-1.5.1) were not smart enough to detect that, so if you were to do a print a
, you'd get [1, 2, [1, 2, [1, 2, [1, 2, [1, 2, [1, 2, ...
etc. in an infinite loop. Since Python 1.5.1, the interpreter detects this, printing [1, 2, [...]]
instead.