2011-11-30 16 views
7
>>> b = [] 
>>> c = '1234' 
>>> b += c 
>>> b 
['1', '2', '3', '4'] 
>>> 

¿Qué está pasando aquí? Esto no debería funcionar, ¿verdad? o me estoy perdiendo algo obvio?Agregar una cadena a una lista

>>> b = [] 
>>> c = '1234' 
>>> b + c 
Traceback (most recent call last): 
    File "<pyshell#7>", line 1, in <module> 
    b + c 
TypeError: can only concatenate list (not "str") to list 
>>> 

Entonces a += b no siempre es equivalente a a = a + b?

+1

¿Es este comportamiento todavía está presente en Python 3.x? Siempre me ha parecido irritante que un tipo de biblioteca estándar rompa el contrato general que 'a + = b' <=>' a = a + b' (sin afectar a ninguna otra referencia al valor 'a' original). –

+2

@Karl Knechtel: lamentablemente, todavía está presente en Python 3.2.1. –

+0

Lo estaba comprobando en python 3.2, sí. Encontré el problema mirando un código para principiantes que estaba produciendo resultados incorrectos. No pude encontrar ninguna referencia a este comportamiento específico en 'Learning Python'. Comprobé PEP203 y dice que se usa '__iadd__' pero también dicen que' __iadd__' es el in situ '__add__' que no es el caso en este caso ... Tal vez alguien podría explicar lo racional debajo de este comportamiento o punto/enlace a alguna discusión sobre eso? Entiendo por el comentario de Karl que hay personas preocupadas por eso – joaquin

Respuesta

2

Una cadena es una secuencia de caracteres. La operación de lista += toma cualquier secuencia y agrega cada uno de los elementos de la secuencia a la lista.

(En realidad += toma cualquier iterable.)

+0

b = b + c falla – joaquin

+2

'+' es un operador diferente que '+ ='. –

+0

Lo sé, se llama asignación aumentada y se define como equivalente a a = a + b (ver PEP203). Tomar esta definición estrictamente me lleva a una expectativa incorrecta. Eso es lo que me sorprendió (probablemente nunca me atreví a agregar una lista a una cadena en mi código python, así que nunca colisioné con esto antes). No debería ser 'Ante la ambigüedad, rechace la tentación de adivinar'? – joaquin

11

Las cadenas son iterable: los elementos son caracteres de la cadena. Cuando agrega un iterable a una lista, los elementos iterativos se anexan a la lista.

Cualquiera de las siguientes hará lo que usted está esperando (es decir, añadir la cadena, se extiende la lista con los personajes de la cuerda):

b += [c] 

o

b.append(c) 
+0

+1 para usar el vocabulario correcto: 'iterable' – gecco

9

El += operador extiende una lista en lugar de anexarla:

>>> b = [] 
>>> c = "1234" 
>>> b.append(c) 
>>> b 
['1234'] 
>>> b.extend(c) 
>>> b 
['1234', '1', '2', '3', '4'] 
>>> b += c 
>>> b 
['1234', '1', '2', '3', '4', '1', '2', '3', '4'] 
>>> b += [c] 
>>> b 
['1234', '1', '2', '3', '4', '1', '2', '3', '4', '1234'] 
+0

¿conoce una fuente de documentación sobre el efecto de estos operadores ('+', '+ =') para iterables/secuencias/...? – moooeeeep

0

¿Qué esperabas? Si desea agregar c como cadena que debe hacer:

b.append(c) 

Salud!

+0

Esperaba que fallara – joaquin

+0

Pero como Tim explicó anteriormente, el comportamiento de + = no es el mismo que + – ocell

+0

, por favor, consulte los comentarios en la publicación de Tim. – joaquin

0

En esencia, el operador + = de la lista recuperará el iterador de c, lo que arrojará los caracteres individuales en orden. Si pretendía agregar la cadena real a la lista, obteniendo el resultado ['1234'], puede usar b.append ('1234') en su lugar.

2

+ = es azúcar sintáctica para extender, pero + es simplemente concatenación de lista. Si se extiende, iterará sobre el argumento, que en este caso es una cadena. Pero no se puede concatenar una cadena a una lista, por lo tanto + falla.

3

Esta es una respuesta no a la pregunta original (que creo que ha sido respondida adecuadamente), sino a las numerosas preguntas que se han formulado en los comentarios sobre la semántica de la asignación aumentada (+= y operaciones similares).

En pocas palabras: la asignación aumentada funciona de manera diferente para los tipos mutables que para los inmutables.

str, tuple, y los tipos numéricos, entre otros, son inmutables. El contenido de una tupla no se pueden cambiar una vez que se ha creado, por lo que obtener este comportamiento:

>>> a = (1, 2) 
>>> b = a 
>>> a += (3, 4) 
>>> a 
(1, 2, 3, 4) 
>>> b 
(1, 2) 

str tiene la misma semántica. Básicamente, a += b es equivalente a a = a + b si a es inmutable.

La mayoría de los otros tipos, incluido list, son mutables.El contenido de una lista puede cambiarse en su lugar, y la asignación aumentada hace exactamente eso. Por lo tanto:

>>> a = [1, 2] 
>>> b = a 
>>> a += [3, 4] 
>>> a 
[1, 2, 3, 4] 
>>> b 
[1, 2, 3, 4] 

Mientras que si la tercera línea se sustituyeron por a = a + [3, 4], una nueva lista se crea y se b sería [1, 2].

Para una clase definida por el usuario, la semántica depende de la forma en que se llevó a cabo, pero así es como se supone que debe ser hecho por PEP 203.

+0

Esta es una muy buena observación. 'a' y' b' comparten la misma dirección de memoria hasta que 'a' se evalúe en el lado izquierdo de un operador de asignación? ¿Podrías incluir eso? – Droogans

Cuestiones relacionadas