Let's see next code:
Try it online!
import numpy as np
def change(in_array, variant = 0):
if variant == 0:
in_array += 1 # line a
elif variant == 1:
in_array = in_array + 1 # line b
elif variant == 2:
in_array[:] = in_array + 1
elif variant == 3:
np.put(in_array, np.arange(in_array.size), in_array + 1)
elif variant == 4:
np.copyto(in_array, in_array + 1)
elif variant == 5:
np.place(in_array, np.ones_like(in_array), in_array + 1)
else:
assert False, variant
print('after, inside', in_array)
orig = np.array([1, 2, 3])
for variant in [0, 1, 2, 3, 4, 5]:
print('variant', variant)
x = np.copy(orig)
print('before', x)
change(x, variant)
print('after, outside', x, ('changed', 'not changed')[bool(np.all(x == orig))])
It outputs:
variant 0
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed
variant 1
before [1 2 3]
after, inside [2 3 4]
after, outside [1 2 3] not changed
variant 2
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed
variant 3
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed
variant 4
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed
variant 5
before [1 2 3]
after, inside [2 3 4]
after, outside [2 3 4] changed
You may see that variant 0 gives correct after answer inside and outside. While variant 1 gives correct only inside.
This is because variant 0 modifies actually given array that was provided in function. While variant 1 creates a modified copy inside function which stays only inside function, the actual passed argument is not modified.
So variant 0 modifies passed argument, while variant 1 modifies a copy of passed argument.
In Python code a = a + 1
inside a function actually creates o a copy of variable a
local in function. And this local variable stays only until function end and is deleted at the end of running function.
Variant 2, a[:]
creates view of original array, it is like a reference to subset of elements of original array, just :
is view to the whole array, assigning to this view modifies original array. Modifiable view is also created by slices like a[1:3]
and indexing like a[2]
or a[[1,2]]
.
Writing a[:] = some_operation(a)
is probably the most intuitive and fastest way of assigning back to a
of modified/transformed copy of a
.
Variants 3, 4, 5 are other fancy ways of assigning right-hand-side expression back to array a
.