3

In numpy subarrays obtained through any of slicing, masking or fancy indexing operations are just views to the original array, which can be demonstrated as follows:

$ python3
Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> np.__version__
'1.11.0'

>>> a = np.arange(3); a[:2] = 111; a
array([111, 111,   2])

>>> a = np.arange(3); a[a<2] = 111; a
array([111, 111,   2])

>>> a = np.arange(3); a[[0,1]] = 111; a
array([111, 111,   2])

In the above example, the entire subarray was assigned to. However if we assign to an element of the subarray, the result of the slicing operation still behaves as a view, whereas the results of the masking and fancy indexing operations behave as independent copies:

>>> a = np.arange(3); a[:2][0] = 111; a
array([111,   1,   2])

>>> a = np.arange(3); a[a<2][0] = 111; a
array([0, 1, 2])

>>> a = np.arange(3); a[[0,1]][0] = 111; a
array([0, 1, 2])

Is this a bug in numpy, or is it by design? If it is by design, then what's the substantiation for such an inconsistency?

Mihai Alexandru-Ionut
  • 47,092
  • 13
  • 101
  • 128
Leon
  • 31,443
  • 4
  • 72
  • 97

1 Answers1

2

It's not a bug. As far as you pass a slice object to Numpy array the returned sub array is a view of the original items which means that even slice assignment or single item assignments will change the original array. But in other cases the returned result is not a view. It's, in fact, a shallow view (copy) of the chosen slice which only supports slice assignment like what other mutable objects in Python support.

It's also mentioned in documentation:

[...] As with index arrays, what is returned is a copy of the data, not a view as one gets with slices.

Mazdak
  • 105,000
  • 18
  • 159
  • 188
  • Ok, this means that I don't yet quite well understand how assignment works in Python. Now my first impression is that `a[i]` is evaluated differently depending on whether it appears on the left side of the assignment operator or not. Rereading the documentation I see that for user-defined objects the assignment `object[expr] = ...` is evaluated via [object.__setitem__](https://docs.python.org/3/reference/datamodel.html#object.__setitem__) while in other contexts [object.__getitem__](https://docs.python.org/3/reference/datamodel.html#object.__getitem__) is used. – Leon May 07 '18 at 13:09
  • @Leon Indeed. That's how setting item and getting item work in Python. – Mazdak May 07 '18 at 13:29