2009-06-12 9 views
5

digamos que tengo una lista¿Cómo puedo operar en el objeto real, no en una copia, en un bucle pitón?

a = [1,2,3] 

Me gustaría incrementar cada elemento de la lista en su lugar. Quiero hacer algo tan sencillo como sintácticamente

for item in a: 
    item += 1 

pero en ese ejemplo Python usa sólo el valor de item, no su referencia real, así que cuando he terminado con ese bucle a sigue devolviendo [1,2, 3] en lugar de [2,3,4]. Sé que podría hacer algo como

a = map(lambda x:x+1, a) 

pero que no encaja realmente en mi código actual y me gustaría tener que volver a escribir que: - \

+0

El bucle for realmente le da el objeto real, no copias. El caso es que estás usando números. Los números (y las cadenas), como todos los valores de Python, son objetos, pero cada literal se refiere a una instancia única. Entonces, si pudieras modificar una instancia que representara de 1 a 2, terminarías cambiando todos los 1 a 2, lo que mataría. La alternativa, tener una instancia para cada valor no sería factible. Intente jugar con la función id: id (1), id ('hello world'), etc. (siempre devuelve la misma dirección para los mismos literales.) – Blixt

Respuesta

18

Aquí ya go:

# Your for loop should be rewritten as follows: 
for index in xrange(len(a)): 
    a[index] += 1 

Por cierto, el artículo ES una referencia al item en a, pero, por supuesto, no puede asignar un nuevo valor a un número entero. Para cualquier tipo mutable, el código funcionaría bien:

>>> a = [[1], [2], [3], [4]] 
>>> for item in a: item += [1] 
>>> a 
[[1,1], [2,1], [3,1], [4,1]] 
+0

Ooooh gracias por aclarar eso – spencewah

9

lugar de su solución basada en map, he aquí una solución lista basada en la comprensión

a = [item + 1 for item in a] 
12

En enteros pitón (y flota, y cadenas y tuplas) son inmutables por lo que tiene el objeto real (y no una copia), simplemente no puede cambiarlo.

Lo que está sucediendo es que en la línea: item += 1 está creando un nuevo entero (con un valor de item + 1) y vinculando el nombre item a él.

Lo que quiere hacer es cambiar el número entero que a[index] señala, por lo que la línea a[index] += 1 funciona. Aún estás creando un nuevo entero, pero luego estás actualizando la lista para señalarlo.

Como nota al margen:

for index,item in enumerate(a): 
    a[index] = item + 1 

... es un poco más idiomática que la respuesta Publicado por tríptico.

+1

Empecé a escribir enumerar y puedo No recuerdo por qué cambié ahora - jaja. Creo que quería apegarme a las funciones que cualquier programador novato probablemente conozca, así que pasé de enumerar a rango (len()), y luego decidí que no quería alentar el uso furtivo de memoria de range(), así que cambié para xrange(). No siempre estoy seguro de cuándo es un buen momento para alentar las mejores prácticas, a veces una mejor práctica es todo lo que el usuario está dispuesto a comprender en este momento. – Triptych

+1

@Triptych: Creo que fue una buena idea mantener las funciones más elementales para un principiante, pero no estoy de acuerdo en que sea importante introducir xrange.Parece al menos tan raro como enumerar, y los documentos dicen que el beneficio de xrange es mínimo excepto en casos patológicos. (Esta también ha sido mi experiencia.) Y xrange ya tiene rango de ortografía en 3.x. –

Cuestiones relacionadas