I have a question regarding variable assignation and memory allocation in a simple case.
Imagine that I am initialising a state vector x
, with initial value x0
. I am then making iterative updates on that state vector with buffer array X
and after each iteration, I store the new state vector in a storage list L
. An outline of my initial implementation can be found in the following snippet:
import numpy as np np.random.seed(11) x0 = 1 L = [x0] x = x0 X = np.zeros((3,1)) for i in range(10): X[-1, :] = np.random.normal() # To simulate operations on X x = X[-1, :] L.append(x) print(L)
Which would print that L holds
[1 array([-1.06560298]) array([-1.06560298]) array([-1.06560298]) array([-1.06560298]) array([-1.06560298]) array([-1.06560298]) array([-1.06560298]) array([-1.06560298]) array([-1.06560298]) array([-1.06560298])]
Because when x
is appended to L, only the reference to X[-1, :]
is added, not the actual value.
The solution I could find is to use np.copy
to copy the values of the last row of X
into x
and then append it, as can be seen in the following snippet.
import numpy as np np.random.seed(11) x0 = 1 L = [x0] x = x0 X = np.zeros((3,1)) for i in range(10): X[-1, :] = np.random.normal() # To simulate operations on X x = np.copy(X[-1, :]) L.append(x) print(L)
The output shows that indeed the modifications on the state x
are correctly recorded.
[1 array([1.74945474]) array([-0.286073]) array([-0.48456513]) array([-2.65331856]) array([-0.00828463]) array([-0.31963136]) array([-0.53662936]) array([0.31540267]) array([0.42105072]) array([-1.06560298])]
I wonder if there would be a more elegant or efficient way to solve this problem?
Thanks!
Advertisement
Answer
Don’t mix numpy arrays and python lists if you can avoid it. If you know the number of iterations, pre-allocate a buffer to hold the whole thing (e.g., with np.empty
):
import numpy as np np.random.seed(11) N = 10 L = np.empty(N) L[0] = 1 X = np.zeros(3) for i in range(N): L[i] = X[-1] = np.random.normal() print(L)
On the other hand, if all you need is to get the scalar from a 1-element array, you can use the item
method:
x = X[:, -1].item()