Python: добавление numpy.array в список python перезаписывает предыдущие элементы

#python #python-3.x #numpy #numpy-ndarray

#python #python-3.x #numpy #numpy-ndarray

Вопрос:

Я пытаюсь построить орбиту звезды в заданном потенциале. Сначала я инициализирую положение и скорость и получаю ускорение из положения в соответствии с заданным потенциалом.

Затем я увеличиваю время с определенным временным шагом и вычисляю орбиту. Проблема возникает, когда я пытаюсь сохранить вычисленные позиции в пустом списке. Вот мой код:

 ## Initial position, velocity, and acceleration
r = np.array([20., 20., 0.])
v = np.array([0., 1., 0.])
g = acc(*r) #calculates acceleration from a function

## empty list to store position data
posdata = []

## Orbit integration
dt = 0.1
for t in np.arange(0, 1000, dt):
    v  = 0.5 * g * dt
    r  = v * dt
    if t%100 == 0:
        print(r) #check if r actually changes
    g = acc(*r)
    v  = 0.5 * g * dt
    posdata.append(r)
  

Это то, что я ожидаю получить:

 posdata
>>> [array([19.999875, 20.099875,  0.]), array([19.99950125, 20.19950001,  0.]), array([19.99887999, 20.29887502,  0.]), ...]
  

Но на самом деле я понимаю это:

 >>> [array([-17.57080611, -34.03696644,   0.]), array([-17.57080611, -34.03696644,   0.]), array([-17.57080611, -34.03696644,   0.])]
  

Все элементы идентичны последнему вычисленному элементу. Как вы можете видеть, я проверил, r действительно ли что-то меняется, и это происходит. Я думаю, это связано с тем, что r это массив, но я не знаю, как это исправить.

Комментарии:

1. r во время цикла остается один и тот же объект, поэтому вы добавляете один и тот же объект к posdata на каждой итерации. Быстрое исправление: r = r v*dt ,

Ответ №1:

Вы добавляете один и тот же объект каждый раз, когда создаете список из множества ссылок на один и тот же объект.

[r, r, r, r, r, r, r]

Поскольку объект является изменяемым, при обновлении объекта изменение влияет на весь ваш список ссылок.

Вам нужно создать копию объекта, когда вы добавляете его в свой список.

Попробуйте это вместо

 posdata.append(r.copy())
  

Теперь у вас будет другой объект в каждом расположении списка.

[r1, r2, r3, r4, r5, r6, r7]

Ответ №2:

Когда вы добавляете массив r в список, добавляется только ссылка на объект array. И поскольку объекты numpy.array изменяемы, все ссылки обновляются на месте. Для этого вы можете либо

  • добавьте массив в виде списка к posdata в виде списка

posdata.append(r.tolist())

Или

  • добавьте массив в качестве нового объекта numpy.array в posdata

    posdata.append(np.array(r))

Ответ №3:

Я столкнулся с той же проблемой. Мое решение состоит в том, чтобы изменить = в уравнении r = v * dt на r = r v * dt , а затем добавить его в список.