Reputation: 2134
If I have a list x = [1, 2, 3]
and pass it to a function f
which uses the operator +=
in the form f(x[:])
, a shallow copy is made and the contents are unchanged:
def f(x):
print "f, x = ", x, ", id(x) = ", id(x)
x += [1]
print "f, x = ", x, ", id(x) = ", id(x)
x = [1,2,3]
print "x = ", x, ", id(x) = ", id(x)
f(x[:])
print "x = ", x, ", id(x) = ", id(x)
Output:
x = [1, 2, 3] , id(x) = 139701418688384
f, x = [1, 2, 3] , id(x) = 139701418790136
f, x = [1, 2, 3, 1] , id(x) = 139701418790136
x = [1, 2, 3] , id(x) = 139701418688384
However, expecting the same behavior for an ndarray
x = np.array([1, 2, 3])
I was surprised that the contents were changed, even though a copy was indeed made:
import numpy as np
def f(x):
print "f, x = ", x, ", id(x) = ", id(x)
x += [1]
print "f, x = ", x, ", id(x) = ", id(x)
x = np.array([1,2,3])
print "x = ", x, ", id(x) = ", id(x)
f(x[:])
print "x = ", x, ", id(x) = ", id(x)
Output:
x = [1 2 3] , id(x) = 139701418284416
f, x = [1 2 3] , id(x) = 139701418325856
f, x = [2 3 4] , id(x) = 139701418325856
x = [2 3 4] , id(x) = 139701418284416
(I know the +[1]
function acts differently for an ndarray vs a list). How can I pass an ndarray like the list and avoid this behavior?
Bonus question Why is the problem resolved by using x = x + [1]
in the function f
?
Upvotes: 2
Views: 490
Reputation: 152725
You can use the copy
method of the numpy-array if you want a copy:
f(x.copy())
Note that even though the id
of x
and x[:]
differs these arrays may share the same memory so changes to one will propagate to the other and vice-versa:
x = np.array([1,2,3])
y = x[:]
np.may_share_memory(x, y) # True
z = x.copy()
np.may_share_memory(x, z) # False
However normally you don't pass copies to a function. You would create a copy inside the function:
def give_me_a_list(lst):
lst = list(lst) # makes a shallow copy
# ...
def give_me_an_array(arr):
arr = np.array(arr) # makes a copy at least if you don't pass in "copy=False".
# ...
Upvotes: 3