2012-08-22 11 views
15

Cuando escribo este código:lista de Python no refleja cambio de variable

polly = "alive" 
palin = ["parrot", polly] 
print(palin) 
polly = "dead" 
print(palin) 

pensé que lo haría salida de esto:

"['parrot', 'alive']" 
"['parrot', 'dead']" 

Sin embargo, no lo hace. ¿Cómo puedo obtenerlo?

+2

relacionada: http://stackoverflow.com/q/11690220/748858 – mgilson

Respuesta

41

variables de Python tienen referencias a los valores . Por lo tanto, cuando defina la lista palin, ingrese el valor al que hace referencia polly, no la variable en sí.

Debe imaginar los valores como globos, con variables que son hilos vinculados a esos globos. "alive" es un globo, polly es solo un hilo de ese globo, y la lista palin tiene un diferente hilo vinculado a ese mismo globo. En Python, una lista es simplemente una serie de temas, todos de partida numerado en 0.

Lo que se hace a continuación es atar la cuerda polly a un nuevo globo "dead", pero la lista todavía se aferra a la vieja hilo atado a el globo "alive".

Puede reemplazar esa cadena por "alive" mantenida por la lista al reasignar la lista por índice para hacer referencia a cada hilo; en su ejemplo que es el hilo 1:

>>> palin[1] = polly 
>>> palin 
['parrot', 'dead'] 

Aquí simplemente Até el hilo palin[1] a lo mismo polly está ligado a, sea lo que sea.

Tenga en cuenta que cualquier colección en python, como dict, set, tuple, etc. son simplemente colecciones de hilos también. Algunos de estos pueden tener sus hilos intercambiados por diferentes hilos, como listas y dicts, y eso es lo que hace que algo en python sea "mutable".

Las cadenas, por otro lado, son no mutable. Una vez que define una cadena como "dead" o "alive", es un globo. Puede atarlo con un hilo (una variable, una lista o lo que sea), pero no puede reemplazar letras dentro de él. Solo puede atar ese hilo a una cadena completamente nueva .

La mayoría de las cosas en python pueden actuar como globos. Los enteros, cadenas, listas, funciones, instancias, clases, todos pueden estar vinculados a una variable o vinculados a un contenedor.

Le recomendamos que lea Ned Batchelder's treatise on Python names también.

+0

Gracias, creo que ahora que hice la pregunta incorrecta pero gracias – Flexo1515

+10

Me gusta la analogía del globo, especialmente si son globos de helio que flotan cuando se suelta la última cuerda ... (+1). – mgilson

+0

@ user1404053: actualicé un poco más para explicar cómo las cadenas no son mutables. Debes reemplazar una cadena "globo" por otra. –

4

Antes de su estado de cuenta segunda impresión, almacenar los nuevos valores en palin:

palin = ["parrot", polly] 
+0

De todas formas para hacerlo sin necesidad de restaurar el nuevo valor? – Flexo1515

+3

@ user1404053: No es la forma en que preguntas. En Python, las cadenas son inmutables, por lo que no hay forma de cambiar el valor en 'polly' y, por lo tanto, cambiarlo en cualquier otro lugar. La línea 'polly =" dead "' es una [operación de reenlace en lugar de una mutación] (http://en.wikipedia.org/wiki/Name_binding#Relación_y_mutación) –

0

La lista contendrá solo valores, no referencias a las variables que desee. Sin embargo, podría almacenar una lambda en la lista y hacer que la lambda busque el valor de su variable.

>>> a = 'a' 
>>> list = ['a',lambda: a] 
>>> list[1] 
<function <lambda> at 0x7feff71dc500> 
>>> list[1]() 
'a' 
>>> a = 'b' 
>>> list[1]() 
'b' 
+0

Algunas explicaciones más: aquí 'lambda: a' es básicamente una función que simplemente devuelve el valor almacenado en' a'. Es por eso que puede usar el comando 'list [1]()'; significa que llamas a la función almacenada en 'list [1]'. (También, gravatar apropiado, @Jonatan) –

+0

Muy bien, gracias por la explicación. También me había olvidado por completo de mi avatar, jaja! – Jonatan

3

Cuando coloca una cadena en una lista, la lista contiene una copia de la cadena.No importa si la cadena fue originalmente una variable, un valor literal, el resultado de una llamada a una función u otra cosa; para cuando la lista lo ve, es solo un valor de cadena. Cambiar lo que generó la cadena más tarde nunca afectará la lista.

Si desea almacenar una referencia a un valor que notará cuándo cambia ese valor, el mecanismo habitual es utilizar una lista que contenga el valor "referenciado". Aplicando eso a su ejemplo, termina con una lista anidada:

polly = ["alive"] 
palin = ["parrot", polly] 
print(palin) 
polly[0] = "dead" 
print(palin) 
0

No puede. La asignación a un nombre simple es que Python siempre vuelve a enlazar el nombre, y no puede personalizar o monitorear esta operación.

Lo que puede hacer es hacer de polly un objeto mutable en lugar de una cadena, y mutar su valor en lugar de volver a enlazar el nombre. Un simple ejemplo:

>>> polly = ['alive'] 
>>> items = ['parrot', polly] 
>>> items 
['parrot', ['alive']] 
>>> polly[0] = 'dead' 
>>> items 
['parrot', ['dead']] 
0

Las otras respuestas explicaron lo que está sucediendo bien.

Este es uno de los (varios) problemas que motivan el uso de los objetos. Por ejemplo, se podría hacer esto:

class Animal: 
    def __init__(self, aniType, name): 
     self.aniType = aniType 
     self.name = name 
     self.isAlive = True 

    def kill(self): 
     self.isAlive = False 

    def getName(self): 
     return self.name 

    def getType(self): 
     return self.aniType 

    def isLiving(self): 
     return self.isAlive 


polly = Animal("parrot", "polly") 

print(polly.getName()+' the '+polly.getType()+' is alive?') 
print(polly.isLiving()) 

polly.kill() 

print(polly.getName()+' the '+polly.getType()+' is alive?') 
print(polly.isLiving()) 

puede parecer una gran cantidad de código en un primer momento para una tarea sencilla, pero los objetos son a menudo el camino a seguir para este tipo de cosas, porque ayudan a mantener todo organizado.

Aquí está la salida de ese programa:

polly the parrot is alive? 
True 
polly the parrot is alive? 
False 
Cuestiones relacionadas