Python function is changing the value of my input, and I can't figure out why
Solution 1
Inside your function, z
and spins
refer to the same list, which is also known by the global name of spin
. If you modify one, those changes are visible through the other names as well. The variable z
is superfluous.
If you want z
to be a copy of spins
then just do:
z = spins[:]
or:
z = list(spins)
Solution 2
The thing you are forgetting is that z
and spins
are essentially the same object. Both point to the same list and have the same elements.
For example:
a = [0]
b = a
b[0] = 1
print a
Result:
[1]
To copy the list instead, try something like this:
a = [0]
b = a[:]
b[0] = 1
print a
Result:
[0]
Solution 3
In Python, all objects are referenced by pointers. All variable names like spin
and test
are just pointers. When you assign spin
to z
you are just making z
point to the same object as spin
and then mutating the object pointed to by z
(which is the same as the object pointed to by spin
).
All function calls in Python are pass-by-value where the values are direct references to objects. Thus, if you mutate a list object within a function, it will appear mutated even after you return from the function.
You have to create a new copy of the list if you don't want to accidentally mutate spin
. Other answers have shown ways of copying a list. I personally like the [:]
syntax that kindall showed in his answer.
Related videos on Youtube
Comments
-
aetb almost 2 years
This is my first question, so if I'm being a total dweeb posting this, let me know why and how I can avoid it in the future!
I have a bit of python code that should just take a list, and multiply the jth component by -1. This is the code in question.
def flip(spins,j): z = spins z[j] = z[j]*-1 return z
However, what I am noticing is that if I try to do something like
spin = [1,1,1] test = flip(spin,1)
it will assign the proper value [1,-1,1] to 'test', but it will also change the value of 'spin' to [1,-1,1]. I know there must be something totally obvious I'm overlooking, but I've been staring at this for 2 hours and still can't see it.
Thanks for your help!
-
roippi over 10 yearsLists are mutable. You're passing a reference to that list to
flip
, making a second reference to that list, then mutating the list.
-
-
aetb over 10 yearsThanks, I had no idea that's how it worked. I thought variables all pointed to unique locations.
-
aetb over 10 yearsI just tried this code a=4 b = a a = 5 print b and it would seem I should get 5, but it actually printed 4. What's the difference here?
-
Shashank over 10 years@aetb The difference is that integers in Python are not mutable. Therefore when you do 'a=5' you are not changing the value of the object pointed to by a. You are actually creating a new integer value '5' and making 'a' point to that.
-
Shashank over 10 years@aetb Lists, on the other hand, are mutable objects. So when you do something like z[j] = z[j]*-1 you are actually just mutating (changing the state of) the list object.
-
embulldogs99 over 2 yearsSo when a function receives an input, it does not put it in a black box of its own. It will actually change the input if that input is edited and used inside the function?
-
kindall over 2 yearsright. a function argument refers to same object that was passed in. if you don't change what object the argument refers to (using
=
specifically) then it's still the same object as was passed in, and any changes you make can be seen by the caller -
Ver Nick over 2 yearsHmm, does not work for me. Whatever method I use, the function still alters the original object.