An array has a shape
, strides
, dtype
and 1d data_buffer. A view
will have its own shape
, strides
, dtype
, and pointer to some place in the base's data_buffer. Indexing with a slice
can be achieved with just these attributes.
But indexing with a list such as your [0,2,1] cannot be achieved this way. So numpy
makes a new array with its own data_buffer, a copy
. That [0,2,1] index list/array is not stored with the copy.
In [43]: A = np.arange(9).reshape(3,3)
In [44]: B = A[[0,2,1],:]
In [45]: A
Out[45]:
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
In [46]: B
Out[46]:
array([[0, 1, 2],
[6, 7, 8],
[3, 4, 5]])
ravel
shows the order of elements in the data_base:
In [47]: A.ravel()
Out[47]: array([0, 1, 2, 3, 4, 5, 6, 7, 8])
The order of elements in B
is different.
In [48]: B.ravel()
Out[48]: array([0, 1, 2, 6, 7, 8, 3, 4, 5])
In contrast, consider a row reordering with a slice:
In [49]: C = A[::-1,:]
In [50]: C
Out[50]:
array([[6, 7, 8],
[3, 4, 5],
[0, 1, 2]])
In [52]: A.strides
Out[52]: (24, 8)
This is achieved by simply changing the strides
:
In [53]: C.strides
Out[53]: (-24, 8)
Transpose is also a view, with changed strides:
In [54]: D = A.T
In [55]: D.strides
Out[55]: (8, 24)
I was going to show the C.ravel()
, but realized that reshape makes a copy (even though C
is a view).
The fundamental point is that anything that numpy
describes as advanced indexing
will make a copy. Changes to the copy will not appear in the original array. https://numpy.org/doc/stable/reference/arrays.indexing.html#advanced-indexing