I am new to python and am trying to understand how it handles copies vs references in respect to list unpacking. I have a simple code snippet and am looking for an explanation as to why it is behaving the way it does.
arr = [1, 2, 3, 4]
[one, two, three, four] = arr
print(id(arr[0]), arr[0])
print(id(one), one)
one = 5
print(id(one), one)
The output is:
(16274840, 1)
(16274840, 1)
(16274744, 5)
I am not sure why one
is all the sudden moved to a different memory location when I try to modify its contents.
I am using python version 2.7.18.
This is my first post, so I apologize in advance if I am not adhering to the guidelines. Please let me know if I have violated them.
Thank you for all the responses. They have helped me boil down my misunderstanding to this code:
var = 1
print(id(var), var)
var = 5
print(id(var), var)
With output:
(38073752, 1)
(38073656, 5)
Asking about lists and unpacking them was completely obfuscatory.
This does a great job of explaining: http://web.stanford.edu/class/archive/cs/cs106a/cs106a.1212/handouts/mutation.html
CodePudding user response:
The id
/address is not associated with the variable/name; it's associated with the data that the variable is referring to.
The 1
object is, in this instance, at address 16274840
, and the 5
object is at address 16274744
. one = 5
causes one
to now refer to the 5
object which is at location 16274744
.
Just to rephrase this in terms of C, I think your question essentially boils down to "why does the following not modify the first element of arr
?" (I'm ignoring unpacking since it isn't actually relevant to the question):
arr = [1, 2, 3, 4]
one = arr[0]
one = 5
I would approximate that code to the following C which also does not modify arr
:
int internedFive = 5;
int arr[4] = {1, 2, 3, 4};
int* one = &arr[0];
one = &internedFive;
printf("%d", arr[0]); // Prints 1
one
originally pointed to the first element of arr
, but was reassigned to point to the 5
. This reassignment of the pointer has no effect on the data location originally pointed to by one
and arr[0]
.
CodePudding user response:
one
is not an object. It's a name that binds to an object. When you reassign one = 5
, you rebind it from the object containing the value 1
, to a different object containing the value 5
, but the only thing one
stores is the updated reference, not the value itself.
To be clear, you can't "modify the contents" of an int
; int
s are immutable. If you want an example where you can modify the contents of an object without modifying the address, consider:
lst = [0]
print(id(lst), lst)
lst[0] = 1
print(id(lst), lst)
which leaves lst
bound to the same list
the whole time, only changing the contents of said list
.