Подтвердить что ты не робот

Проблема с присвоением массива numpy

У меня странная проблема в Python 2.6.5 с помощью Numpy. Я назначаю массив numpy, а затем приравниваю к нему новую переменную. Когда я выполняю любую операцию с новым массивом, исходные значения также меняются. Почему это? См. Пример ниже. Пожалуйста, просветите меня, поскольку я довольно новичок в Python и вообще программировании.

-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]])
4b9b3361

Ответ 1

Это вообще не проблема; это способ, которым массивы (и другие объекты) работают на Python.

Подумайте об этом так: массив, который вы создали в вашем примере кода, является объектом, который находится в каком-то месте в памяти. Но вы не можете использовать его в своей программе, говоря Python, где в памяти идти искать его; вы должны дать ему имя. Когда вы пишете

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

вы создаете массив и создаете имя a, которое ссылается на него. С этого момента Python знает, что a ссылается на "адрес памяти 0x123674283" (или что-то еще). Там есть внутренняя таблица в среде исполнения Python (называемая "таблицей символов", если я правильно помню), которая содержит всю эту информацию, поэтому после выполнения вышеуказанной строки кода Python эта таблица будет содержать

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

Когда вы присваиваете значение одной переменной другой, например

b = a

Python не копирует весь массив, потому что если это большой массив, это займет много времени. Вместо этого он переходит в таблицу символов и копирует адрес памяти для a в новую строку в таблице для b. Таким образом, вы завершаетесь с

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

Итак, вы видите, a и b на самом деле ссылаются на одно и то же место в памяти, то есть на тот же объект. Любые изменения, внесенные вами в один, будут отражены в другом, так как они всего лишь два имени для одного и того же.

Если вы хотите сделать копию массива, вы должны вызвать метод, чтобы сделать это явно. Массивные массивы имеют метод copy, который можно использовать только для этой цели. Поэтому, если вы пишете

b = a.copy()

тогда Python сначала сделает копию массива, то есть он отложит новую область памяти, скажем, по адресу 0x123904381, затем перейдет на адрес памяти 0x123674283 и скопирует все значения массива из последнего раздел памяти для первого. Таким образом, у вас есть тот же контент, который находится в двух разных местах в памяти.

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

Теперь, когда вы меняете один из элементов b, это изменение не будет отображаться в a, так как a и b больше не относятся к тому же разделу памяти компьютера. Поскольку есть две независимые копии данных массива, вы можете изменить один, не затрагивая другого.

Ответ 2

Вкратце, присваивание переменной создает новую ссылку на существующий объект.

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