Suppose I have this function
>>>a=3
>>>def num(a):
a=5
return a
>>>num(a)
5
>>>a
3
Value of a doesnt change.
Now consider this code :
>>> index = [1]
>>> def change(a):
a.append(2)
return a
>>> change(index)
>>> index
>>> [1,2]
In this code the value of index changes. Could somebody please explain what is happening in these two codes. As per first code, the value of index shouldnt change(ie should remain index=[1]).
-
possible duplicate of Class variables behave differently for list and int? (pertains to class variables, but the same mechanism is at work there).Fred Foo– Fred Foo2013年08月24日 16:03:00 +00:00Commented Aug 24, 2013 at 16:03
-
Updated my answer with id function. It might let you understand things better.thefourtheye– thefourtheye2013年08月24日 16:10:11 +00:00Commented Aug 24, 2013 at 16:10
-
1relevant stackoverflow.com/questions/986006/…vinita– vinita2013年08月24日 19:06:40 +00:00Commented Aug 24, 2013 at 19:06
4 Answers 4
You need to understand how python names work. There is a good explanation here, and you can click here for an animation of your case.
If you actually want to operate on a separate list in your function, you need to make a new one, for instance by using
a = a[:]
before anything else. Note that this will only make a new list, but the elements will still be the same.
5 Comments
a.append(2) with a = a.copy(). This will create a new list with contents of your index and assign it to a. This will create a shallow copy of index - all elements that were inside index are shared between index and a so if index[0] is a dictionary, doing a[0]['test'] = 1 would be visible in index[0]. If you want to deep copy the list, see deepcopy list(a).b=copy(a) (it changes the type of a but oh well). I do recommend looking at deepcopy and a function: id("thingie").The value of index doesn't change. index still points to the same object it did before. However, the state of the object index points to has changed. That's just how mutable state works.
7 Comments
list object (and other objects) are more complex than that, but the low-level details are not important here. The relevant point is that the value that index refers to doesn’t change. The content of that value changes but not the value itself.num function as void* num(void* a). Explanation using C (not necessarily fully accurate): a = 3 creates a void* a = &(int object of 3). Now calling num(a) causes the function to receive a copied pointer to int object of 3, not a reference to the pointer.Line 3 in the first block of code is assignment and in the second block is mutation, and that's why you are observing that behavior.
3 Comments
global a statement before changing it's value. Also make sure that there is no other variable named a in the scope you are using global a.integer which is immutable where as in the second block it's a list which can mutated via append, extend, etc attributes of an object of type list.The issue you are encountering is:
a = 3
def num(a):
# `a` is a reference to the argument passed, here 3.
a = 5
# Changed the reference to point at 5, and return the reference.
return a
num(a)
The a in the num function is a diffrent object than the a defined globally.
It works in case of the list because a points at the list passed, and you modify the object being referenced to by the variable, not the reference variable itself.