Ellipsis enumerates [...] and concatenates a list in Python

*** EDIT: I was reckless in my original examples. The behavior does not occur when I add list A to myself, but when I add a list containing list A to A. See the examples below.


I am trying to understand how ellipsis lists (those lists that appear as [...] and appear when you have links to the list) work in Python (2).

In particular, I want to know why, if A is a list, A = A + A seems to work differently with A += A (and A.append(A) )

This is why you get:

 >>> a = [1, 2] >>> a = a + [a] >>> a [1, 2, [1, 2]] 

against.

 >>> a = [1, 2] >>> a += [a] >>> a [1, 2, [...]] 

(Note that a.append (a) seems to work for me just like the last one did.)

Any additional, more general information about this elliptical list phenomenon would also be greatly appreciated if this helps clarify the situation.

Thanks.

+7
source share
3 answers

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, [...]] .

+6
source

Consider the following:

 In [179]: a = [1, 2] In [180]: a+=a In [181]: a Out[181]: [1, 2, 1, 2] In [182]: a.append(a) In [183]: a Out[183]: [1, 2, 1, 2, [...]] In [184]: a[5] ----------------------------------------------- IndexError Trace C:\Users\Marcin\Documents\oneclickcos\oneclickc ----> 1 a[5] IndexError: list index out of range In [185]: a[4] Out[185]: [1, 2, 1, 2, [...]] In [186]: a[3] Out[186]: 2 In [187]: a[4] Out[187]: [1, 2, 1, 2, [...]] In [188]: a Out[188]: [1, 2, 1, 2, [...]] In [189]: a[4][3] Out[189]: 2 In [190]: a[4][4] Out[190]: [1, 2, 1, 2, [...]] In [191]: a[4][5] ----------------------------------------------- IndexError Trace C:\Users\Marcin\Documents\oneclickcos\oneclickc ----> 1 a[4][5] IndexError: list index out of range In [192]: a[4][4] Out[192]: [1, 2, 1, 2, [...]] In [193]: a = [1, 2] In [194]: a+=a In [195]: a Out[195]: [1, 2, 1, 2] In [196]: a Out[196]: [1, 2, 1, 2] In [197]: a Out[197]: [1, 2, 1, 2] In [198]: a.append(a) In [200]: a Out[200]: [1, 2, 1, 2, [...]] In [201]: a.append(a) In [202]: a Out[202]: [1, 2, 1, 2, [...], [...]] In [203]: a[4] Out[203]: [1, 2, 1, 2, [...], [...]] In [204]: a[5] Out[204]: [1, 2, 1, 2, [...], [...]] In [205]: id(a) Out[205]: 64692680L In [206]: id(a[5]) Out[206]: 64692680L In [207]: id(a[4]) Out[207]: 64692680L In [208]: id(a) == id(a[4]) and id(a[4]) == id(a[5]) Out[208]: True 

Note first of all that += does not create an ellipsis list.

Secondly, you can see that the ellipsis list indicates that access to this slot will return the same list. An ellipsis list is a pointer to an external list (or almost certainly an external list, if there is more than one nesting level).

0
source

This is because a = a + a corresponds to a.extend(a) , which Expand the list by adding all the elements in the specified list . Another way to look at this is that the + operator results in "concatenation of s and t" .

This contrasts with a += a , which corresponds to a.append(a) , which "adds an item at the end of the list . "

Hope this clarifies the situation.

0
source

All Articles