2010-06-17 15 views
27

Tengo un problema extraño en Python 2.6.5 con Numpy. Asigno una matriz numpy, luego le asigno una nueva variable. Cuando realizo cualquier operación a la nueva matriz, los valores del original también cambian. ¿Porqué es eso? Por favor mira el ejemplo a continuación. Amablemente ilumíname, ya que soy bastante nuevo en Python, y la programación en general.problema de asignación de matrices numpy

-Sujan

>>> import numpy as np 
>>> a = np.array([[1,2],[3,4]]) 
>>> b = a 
>>> b 
array([[1, 2], 
     [3, 4]]) 
>>> c = a 
>>> c 
array([[1, 2], 
     [3, 4]]) 
>>> c[:,1] = c[:,1] + 5 
>>> c 

array([[1, 7], 
     [3, 9]]) 
>>> b 
array([[1, 7], 
     [3, 9]]) 
>>> a 
array([[1, 7], 
     [3, 9]]) 

Respuesta

56

Que en realidad no es un problema en absoluto; es la forma en que las matrices (y otros objetos) funcionan en Python.

Piénsalo de esta manera: la matriz que creaste en tu ejemplo de código es un objeto que se encuentra en algún lugar de la memoria. Pero no puede usarlo en su programa diciéndole a Python dónde está en la memoria para buscarlo; tienes que darle un nombre. Cuando se escribe

a = np.array([[1,2],[3,4]]) 

que ambos estén de crear la matriz y la creación de un nombre, a, que se refiere a ella. Desde ese momento, Python sabe que a se refiere a "dirección de memoria 0x123674283" (o lo que sea). Hay una tabla interna en el tiempo de ejecución de Python (llamada la "tabla de símbolos" si no recuerdo mal) que contiene toda esta información, por lo que después de la línea anterior de código Python se ejecuta, esta tabla contendría

..., 
'a' : 0x123674283, 
... 

Cuando se asigna el valor de una variable a otra, al igual que

b = a 

Python no copia todo el conjunto, ya que si se tratara de una gran variedad, se tardaría mucho tiempo. En su lugar, va a la tabla de símbolos y copia la dirección de memoria para a en una nueva fila en la tabla para b. Así que terminan con

..., 
'a' : 0x123674283, 
..., 
'b' : 0x123674283, 
... 

Así que ya ves, a y b están refiriendo en realidad a la misma ubicación en la memoria, es decir, el mismo objeto. Cualquier cambio que realice en uno se reflejará en el otro, ya que son solo dos nombres para la misma cosa.

Si realmente desea hacer una copia de la matriz, debe llamar a un método para hacerlo explícitamente. Las matrices Numpy tienen un método copy que puede usar solo para este propósito. Así que si usted escribe

b = a.copy() 

entonces Python primera realidad hacer una copia de la matriz - es decir, que deja de lado una nueva región de memoria, digamos en la dirección 0x123904381, a continuación, pasa a la dirección de memoria 0x123674283 y copia todos los valores de la matriz desde la última sección de la memoria hasta la anterior. Entonces tiene el mismo contenido sentado en dos lugares diferentes en la memoria.

..., 
'a' : 0x123674283, 
..., 
'b' : 0x123904381, 
... 

Ahora, al cambiar uno de los elementos de b, que el cambio no se mostrará en a, ya a y b ya no se refieren a la misma sección de la memoria del ordenador. Como hay dos copias independientes de los datos de matriz, puede cambiar una sin afectar a la otra.

+6

Muchas gracias por la excelente descripción. Huelga decir que eso solucionó el problema, pero realmente aprecio que se tome el tiempo para explicar las cosas. ¡Me has iluminado! – Sujan

+1

"Python no copia toda la matriz, porque si fuera una gran matriz, llevaría mucho tiempo". - Diría que es menos sobre el tiempo que llevaría y más que si no implementa las cosas de esta manera, necesita introducir algo como un tipo de puntero separado, y eso complica las cosas. – user2357112

1

En pocas palabras, una asignación de variable crea una nueva referencia al objeto existente.

A = object # A points to object in memory 
    B = A  # B points to the same object 
Cuestiones relacionadas