проблема присвоения массивов - PullRequest
30 голосов
/ 17 июня 2010

У меня странная проблема в Python 2.6.5 с 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]])

Ответы [ 2 ]

63 голосов
/ 17 июня 2010

Это вообще не проблема; это способ, которым массивы (и другие объекты) работают в 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 фактически ссылаются на одно и то же место в памяти, то есть один и тот же объект. Любые изменения, внесенные вами в одно, будут отражены в другом, поскольку это всего лишь два имени для одной и той же вещи.

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

b = a.copy()

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

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

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

2 голосов
/ 12 октября 2016

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

  A = object   # A points to object in memory
  B = A        # B points to the same object
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...