unexpected result in numpy array slicing (view vs copy)

arrays, numpy, python, scipy, slice

Solution

The above is no different than:

>>> a=np.arange(5)
>>> b=a
>>> b
array([0, 1, 2, 3, 4])

>>> b+=5
>>> a
array([5, 6, 7, 8, 9])
>>> b
array([5, 6, 7, 8, 9])

>>> b=b+5
>>> b
array([10, 11, 12, 13, 14])
>>> a
array([5, 6, 7, 8, 9])

Which, at least to me, seem like completely expected behavior. The `b+=x` operator calls `__iadd__` which importantly first tries to modify the array in place, so it will update `b` which is still a view of `a`. While the `b=b+x` operator calls `__add__` which creates new temporary data and then assigns it to `b`.

For `a[i] +=b` the sequence is (in numpy):

a.__setitem__(i, a.__getitem__(i).__iadd__(b))

Problem

I'm trying to reduce the amount of copying in my code and I came across surprising behavior when dealing with numpy array slicing and views, as explained in: Scipy wiki page on copying numpy arrays I've stumbled across the following behavior, which is unexpected for me: Case 1.: ``` import numpy as np a = np.ones((3,3)) b = a[:,1:2] b += 5 print a print b.base is a ``` As expected, this outputs: ``` array([[ 1., 6., 1.], [ 1., 6., 1.], [ 1., 6., 1.]]) True ``` Case 2: When performing the slicing and addition in one line, things look different: ``` import numpy as np a = np.ones((3,3)) b = a[:,1:2] + 5 print a print b.base is a ``` The part that's surprising to me is that a[:,1:2] does not seem to create a view, which is then used as a left hand side argument, so, this outputs: ``` array([[ 1., 1., 1.], [ 1., 1., 1.], [ 1., 1., 1.]]) False ``` Maybe someone can shed some light on why these two cases are different, I think I'm missing something. Solution: I missed the obvious fact that the "+" operator, other than the in-place operator "+=" will always create a copy, so it's in fact not related but slicing other than how in-place operators are defined for numpy arrays. To illustrate this, the following generates the same output as Case 2: ``` import numpy as np a = np.ones((3,3)) b = a[:,1:2] b = b + 5 print a print b.base is a ```

Original source