2012-03-20 6 views
7

*** EDITAR: Fui descuidado en mis ejemplos originales. El comportamiento no ocurre cuando agrego la lista A a sí mismo, sino cuando agrego una lista que contiene lista A a A. Por favor vea los ejemplos corregidos a continuación.Ellipsis enumera [...] y concatena una lista a sí mismo en Python


estoy tratando de entender cómo las listas de puntos suspensivos (esas listas que aparecen como [...] y se producen cuando usted tiene una lista referencia a sí mismo) trabaja en Python (2).

En particular, quiero saber por qué, si A es una lista, A = A + A parece funcionar de manera diferente a A += A (y A.append(A))

Es decir, ¿por qué se obtiene:

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

vs .

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

(Tenga en cuenta que a.append (a) parece funcionar para mí al igual que este último lo hizo.)

Cualquier información adicional más general con respecto a este fenómeno de la lista de puntos suspensivos también sería muy apreciada si ayuda a aclarar las cosas.

Gracias.

+0

http://stackoverflow.com/questions/2347265/what-does-plus-equals-do-in-python – Dogbert

+1

'a = [1, 2]; a + = a' hará '[1, 2, 1, 2]', no '[1, 2, [1, 2]'. Ver la pregunta duplicada – khachik

+1

El llamado duplicado no discute las listas de elipsis * en absoluto *. – Marcin

Respuesta

6

Editar: (para abordar las cuestiones adicionales planteadas por las modificaciones a la pregunta):

a = a + b y a += b no son la misma operación. El primero ejecuta a.__add__(b), este último ejecuta a.__iadd__(b) ("in-place add").

La diferencia entre los dos es que el primero siempre crea un nuevo objeto (y vuelve a vincular el nombre a con ese nuevo objeto) mientras que el segundo modifica el objeto in situ (si puede, y con una lista, puede)

Para ilustrar esto, basta con ver las direcciones de sus objetos:

>>> a = [1, 2] 
>>> id(a) 
34660104 
>>> a = a + [a] 
>>> id(a) 
34657224 
>>> id(a[2]) 
34660104 

La "nueva" a se construyó a partir de cero, primero tomando los valores de la lista de edad a, a continuación, concatenando la referencia a la viejo objeto a eso.

Contraste esto:

>>> a = [1, 2] 
>>> id(a) 
34658632 
>>> a += [a] 
>>> id(a) 
34658632 
>>> id(a[2]) 
34658632 

(respuesta de edad, que explican las referencias cíclicas):

Considere esto:

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

tanto, para resumir la primera parte:

Para listas, a += a es equivalente a llamar al a.extend(a) que modifica a en el lugar, agregando copias de los elementos encontrados en a al comienzo de esta operación.

Por el contrario, a += [a] corresponde a a.append(a), los cuales crean una referencia a la lista a (i. E. Un puntero a su dirección en la memoria) y añadir que a la lista. Lo cual constituye una llamada "referencia cíclica".

Si se va a mirar a la representación interna de a en ese punto, se vería algo como esto:

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 

versiones antiguas de Python (pre-1.5.1) no eran lo suficientemente inteligente como para detectar que , por lo que si tuviera que hacer un print a, obtendría [1, 2, [1, 2, [1, 2, [1, 2, [1, 2, [1, 2, ... etc. en un bucle infinito. Desde Python 1.5.1, el intérprete detecta esto, imprimiendo [1, 2, [...]] en su lugar.

0

considerar lo siguiente:

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 

Aviso en primer lugar que += no crea una lista de puntos suspensivos.

En segundo lugar, se puede observar que la lista de puntos suspensivos indican que accediendo esa ranura volverá exactamente la misma lista - la lista de puntos suspensivos representa un puntero a la lista exterior (o, casi ciertamente un lista externa si hay más de un nivel de anidación).

Cuestiones relacionadas