Reputation: 17617
I have a function that takes a list or numpy array v. The function modify v so also the original vector x changes (because of curse this is a reference). I would like to have the old value of x. There are some easy solutions to this but they do not look very elegant.
What is the most pythonic way to solvethis problem?
Let consider for example
def change_2(v):
v[2]=6
return v
x=[1,2,3]
z=change_2(x)
print "x=", x,"z=",z
x= [1, 2, 6] z= [1, 2, 6] #I would like x=[1, 2, 3]
Upvotes: 1
Views: 393
Reputation: 63737
Everything in Python is reference. If you need an immutable argument, pass a copy.
A copy can easily be created as v[:]
or as list(v)
So your call becomes
z=change_2(x[:])
The first notation, uses the slice notation to create a copy of the list. In case, your list have mutable references within, you would need deepcopy, which can be achieved through copy.deepcopy
For Numpy arrays as @delnan has commented, slice notation returns a view rather than a copy. To get over it, for numpy arrays use the copy
method
>>> def foo(v):
v[0] = 1
>>> v = np.zeros(5)
>>> foo(v.copy())
>>> v
array([ 0., 0., 0., 0., 0.])
Upvotes: 2
Reputation: 1121942
Create a copy of the list:
def change_2(v):
v = v[:]
v[2] = 6
return v
Python is already giving you the value, the object itself. You are altering that value by changing its contents.
v[:]
takes a slice of all indices in the list, creating a new list object to hold these indices. An alternative way would be to use the list()
constructor:
v = list(v)
Another alternative is to leave the responsibility of creating a copy up to the caller:
def change_2(v):
v[2] = 6
return v
x = [1,2,3]
z = change_2(x[:])
By creating a full copy first, you now have a different value.
Upvotes: 3
Reputation: 239473
Just create a copy of the list, modify and return the copy
def change_2(v):
w = v[:] # Create a copy of v
w[2] = 6 # Modify the copy
return w # Return the copy
Upvotes: 1