How does python handle list unpacking, redefinition, and reference?

Question:

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

Asked By: freedom35

||

Answers:

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].

Answered By: Carcigenicate

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; ints 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.

Answered By: ShadowRanger
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.