1

I recently found a solution to a problem I find bizarre and would like to better understand the situation. The problem involves over-writing values at specified indices of an array.

import numpy as np

# create array to overwrite
mask = np.ones(10)

# first set of index-value pairs
idx_1 = [0, 3, 4]
val_1 = [100, 200, 300]

# second set of index-value pairs
idx_2 = [1, 5, 6]
val_2 = [250, 505, 650]

# third set of index-value pairs
idx_3 = [7, 8, 9]
val_3 = [900, 800, 700]

def overwrite_mask(mask, indices, values):
    """ This function overwrites elements in mask with values at indices. """
    mask[indices] = values
    return mask

# incorrect
# res_1 = overwrite_mask(mask[:], idx_1, val_1)
# res_2 = overwrite_mask(mask[:], idx_2, val_2)
# res_3 = overwrite_mask(mask[:], idx_3, val_3)
# >> [ 100.  250.    1.  200.  300.  505.  650.  900.  800.  700.]
# >> [ 100.  250.    1.  200.  300.  505.  650.  900.  800.  700.]
# >> [ 100.  250.    1.  200.  300.  505.  650.  900.  800.  700.]

# correct
res_1 = overwrite_mask(mask.copy(), idx_1, val_1)
res_2 = overwrite_mask(mask.copy(), idx_2, val_2)
res_3 = overwrite_mask(mask.copy(), idx_3, val_3)
# [ 100.    1.    1.  200.  300.    1.    1.    1.    1.    1.]
# [   1.  250.    1.    1.    1.  505.  650.    1.    1.    1.]
# [   1.    1.    1.    1.    1.    1.    1.  900.  800.  700.] 

I was under the impression that [:] applied after an array produced an exact copy of the array. But it seems as though [:] isn't working as it should in this context.

What is happening here?

1
  • 2
    The semantics you have in mind apply to lists where L[:] is used by many to make a "slice copy". The numpy default behavior is to avoid copies if possible, so if you want a copy you have to ask for one very explicitly. mask[:] returns not a copy but a view, a new object that shares the data with mask. The output you are seeing is the cumulative effect of your three overwrites. Commented Nov 30, 2017 at 12:01

1 Answer 1

3

I was under the impression that [:] applied after an array produced an exact copy of the array.

That's wrong. The [:] applied to instances of Python types like list, str, ... will return a "shallow" copy but that doesn't mean the same applies to NumPy arrays.

In fact NumPy will always return views when "basic slicing" is used. Because [:] is basic slicing it will never copy the array. See the documentation:

All arrays generated by basic slicing are always views of the original array.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.