2012-05-25 14 views
7

estoy trabajando a través Udacity y Dave Evans presenta un ejercicio sobre las propiedades de lista¿Por qué el operador + no cambia una lista mientras que .append() lo hace?

list1 = [1,2,3,4] 
list2 = [1,2,3,4] 

list1=list1+[6] 
print(list1) 
list2.append(6) 
print(list2) 

list1 = [1,2,3,4] 
list2 = [1,2,3,4] 

def proc(mylist): 
    mylist = mylist + [6] 

def proc2(mylist): 
    mylist.append(6) 

# Can you explain the results given by the four print statements below? Remove 
# the hashes # and run the code to check. 

print (list1) 
proc(list1) 
print (list1) 

print (list2) 
proc2(list2) 
print (list2) 

La salida es

[1, 2, 3, 4, 6] 
[1, 2, 3, 4, 6] 
[1, 2, 3, 4] 
[1, 2, 3, 4] 
[1, 2, 3, 4] 
[1, 2, 3, 4, 6] 

Así, en función de la adición de un 6 a la serie, pero no muestra lo hace cuando no está en una función?

Respuesta

15

Entonces, ¿en una función no se muestra la adición de 6 al conjunto pero no cuando no está en una función?

No, eso no es lo que sucede.

Lo que pasa es que, cuando ejecuta mylist = mylist + [6], está creando efectivamente una lista completamente nueva y colocándola en la variable local mylist. Esta variable mylist desaparecerá después de la ejecución de la función y la lista recién creada desaparecerá también.

OTOH cuando ejecuta mylist.append(6) no crea una nueva lista. Obtiene la lista ya en la variable mylist y agrega un nuevo elemento a esta misma lista. El resultado es que la lista (apuntada por list2 también) se modificará. La variable mylist desaparecerá de nuevo, pero en este caso modificó la lista original.

Veamos si una explicación más visual puede ayudar :)

lo que sucede cuando se llama a proc()

Cuando se escribe list1 = [1, 2, 3, 4, 5] va a crear un nuevo objeto de lista (en el lado derecho de los iguales signo) y crear una nueva variable, list1, que apuntará a este objeto.

Creating new list instance and global variable

Entonces, cuando se llama proc(), se crea otra nueva variable, mylist, y puesto que se pasa list1 como parámetro, mylist va a apuntar al mismo objeto:

Calling method creates local variable

Sin embargo , la operación mylist + [6]crea un objeto de lista completamente nuevo cuyo contenido es el contenido del objeto apuntado por mylist más el contenido del siguiente objeto de la lista, es decir, [6]. Dado que atribuye este nuevo objeto a mylist, nuestro escenario cambia un poco y mylist no apunta al mismo objeto apuntado por list1 más:

mylist points to new list object

Lo que no he dicho es que mylist es una variable local : desaparecerá después del final de la función proc(). Por lo tanto, cuando la ejecución proc() terminó, el mylist se ha ido:

mylist is gone

Dado que no hay otros puntos variables en el objeto generado por mylist + [6], desaparecerá, también (ya que el recolector de basura * va a recogerla):

GC collects the list

Tenga en cuenta que, al final, el objeto apuntado por list1 no se cambia.

¿Qué ocurre cuando se llama proc2()

Todo cambia cuando se llama proc2(). En un primer momento, que es lo mismo: se crea una lista ...

Creating new list instance and global variable

... y pasarlo como parámetro a una función, lo que generará una variable local:

Calling method creates local variable

Sin embargo, en lugar de utilizar el operador de concatenación +, que genera una nueva lista, aplica el método append() a la lista existente. El método append()no crea un nuevo objeto; En su lugar, _changes la existente:

Appending a value to a list

Después del final de la función, la variable local desaparecerá, pero el objeto original señalado por él y por list1 será ya alterada:

It is still altered

Dado que todavía apunta por list1, la lista original no se destruye.

EDITAR: si quieres echar un vistazo a todas estas cosas sucediendo ante sus ojos sólo tiene que ir a this radically amazing simulator:

enter image description here

* Si usted no sabe lo que es recolector de basura. .. bueno, lo descubrirás poco después de entender tu propia pregunta.

+5

También hay un buen [servicio] (http://people.csail.mit.edu/pgbovine/python/tutor.html#mode=edit) para ir paso a paso al código python y observar todas las variables en el navegador. Muy cerca de lo que escribiste, @brandizzi – stalk

+0

+1 para dibujo tan bueno ... – gsagrawal

+0

@stalk No conocía este servicio. es simplemente genial! ¡Gracias! – brandizzi

2

lo general, en el primer caso, en función de proc sólo sería capaz de cambiar la lista global de asignación si usted declaró

global mylist 

primera y no pasar mylist como parámetro. Sin embargo, en este caso, aparecerá un mensaje de error que indica que mylist es global y local: name 'mylist' is local and global. Lo que sucede en proc es que se crea una lista local cuando se lleva a cabo la tarea. Dado que las variables locales desaparecen cuando la función finaliza, el efecto de cualquier cambio en la lista local no se propaga al resto del programa cuando se imprime posteriormente.

Pero en la segunda función proc2 está modificando la lista añadiendo en lugar de asignar a la misma, por lo que no es necesario y los cambios en la lista muestran otra parte la palabra clave global.

3

Las variables en python siempre se pueden considerar referencias. Cuando llama a una función con un argumento, está pasando una referencia a los datos reales.

Cuando utiliza el operador de asignación (=), está asignando ese nombre para hacer referencia a un objeto completamente nuevo. Por lo tanto, mylist = mylist + [6] crea una nueva lista que contiene los contenidos anteriores de mylist, así como también 6, y asigna la variable lista my para hacer referencia a la nueva lista. lista1 sigue apuntando a la lista anterior, por lo que nada cambia.

Por otro lado, cuando usa .append, eso de hecho agrega un elemento a la lista a la que hace referencia la variable - no asigna nada nuevo a la variable. Entonces su segunda función modifica la lista a la que se refiere la lista2.

0

Esto, de una forma u otra, es una pregunta muy común. Tomé un golpe para explicar el parámetro de Python pasándome a couple days ago. Básicamente, uno de estos crea una nueva lista y el otro modifica la existente. En este último caso, todas las variables que hacen referencia a la lista "ven" el cambio porque sigue siendo el mismo objeto.

0

En la tercera línea, que hicieron esto

list1=list1+[6] 

Por lo tanto, cuando se hizo el siguiente después de la línea anterior,

print (list1) 

que imprimió lista1 que creó en el procedimiento de arranque y proc que agrega list1 + [6] que está creando una nueva lista dentro de la función proc. Cuando, como cuando se agrega [6], no está creando una nueva lista, sino que está agregando un elemento de la lista a la lista existente.

Pero, tenga en cuenta. En la línea 7, que de nuevo ha creado la lista

list1 = [1,2,3,4] 

Ahora se desea imprimir la lista1 llamando explícitamente, que se imprima la lista1 que reinicializa nuevo, pero no la anterior.

0

Además de las amplias respuestas ya dadas, también vale la pena ser consciente de que si desea que la misma sintaxis de aspecto como:

mylist = mylist + [6] 

...pero todavía quiere que la lista se actualiza "en su sitio", que puede hacer:

mylist += [6] 

que, si bien parece que haría lo mismo que la primera versión, se realidad lo mismo que:

mylist.extend([6]) 

(Tenga en cuenta que extend toma el contenido de un iterable y les añade uno a uno, mientras que append toma lo que se da y se añade que como un único elemento. Ver append vs. extend para una explicación completa.)

Cuestiones relacionadas