List behaviour in Python

Question:

I understand that the following code:

list_1 = [1]
list_2 = list_1
list_1[0] = 2
print(list_2)

gives 2 as output.

However, what I do not understand is that

list_1 = [1]
list_2 = list_1
list_1 = 2
print(list_2)

Does not give 2 as an output, but 1 instead?

Asked By: BertHobe

||

Answers:

A Python variable is a symbolic name that is a reference or pointer to an object. Multiple variables can point to the same object. Changing a variable assignment for one variable does not change the value of another variable.

Must understand what the code list_2 = list_1 vs list_1[0] = 2 means. The first is a variable assignment (or binding) and the second is object manipulation.
This is an important distinction.

  1. variable assignment
    The code list_2 = list_1 does NOT mean that list_2 is an alias to list_1 variable. The variables list_1 and list_2 are object references or pointers to objects. Changing list_2 or list_1 to reference to a different object will not affect the other.

  2. object manipulation
    The code list_1[0] = 2 changes the contents of the list object and not the assignment of the list_1 variable.

The following annotates the code statements with that each line is doing:

list_1 = [1]     => list_1 points to list object with value [1]
list_2 = list_1  => list_2 gets a reference to same object pointed to by list_1
list_1 = 2       => list_1 now points to object with value 2
print(list_2)    => list_2 still points to list object so value is still [1]

You can print out the identity of the object with the id() function which uniquely defines the object and is constant for the life of the object.

Here is a table showing the line of code in each step, values of each variable after code is executed, and id() of the variables to print the referenced object.

step code values id()
1 list_1 = [1] list_1 == [1] id(list1) = 2989298572224
2 list_2 = list_1 list_1 == [1]
list_2 == [1]
id(list1) = 2989298572224
id(list2) = 2989298572224
Both point to same object
3 list_1 = 2 list_1 == 2
list_2 == [1]
id(list1) = 140706891962064 => different object
id(list2) = 2989298572224

After step 2, both variable list_1 and list_2 point to a list object with value [1].

After step 3, list_1 points a different object (i.e. integer object), but list_2 is unchanged so printing list_2 at this point prints [1] not 2.

A related tutorial may help to visualize variable assignment and object references.

Answered By: CodeMonkey

Please extend your code a little bit:

list_1 = [1]
list_2 = list_1
list_1[0] = 2
print(id(list_2) == id(list_1))
print(list_2, type(list_2))
print(list_2[0], type(list_2[0]))
print(list_1, type(list_1))
print(list_1[0], type(list_1[0]))

to see that all the time you are operating on one list.

Now extend the second snippet to see that list_1 no longer references any list in the end:

list_1 = [1]
list_2 = list_1
list_1 = 2
print(id(list_2) == id(list_1))
print(list_2, type(list_2))
print(list_2[0], type(list_2[0]))
print(list_1, type(list_1))
print(list_1[0], type(list_1[0]))

effectively causing the last line to throw an exception.

Answered By: ElmoVanKielmo

This is mainly because in Python everything is considered an object therefore when you pass an variable pointing to a list into another variable it accepts not the variable but the object of the variable inside it therefore referencing it. That is why when you changed the list_1 values it modified the object and therefore in turn list_2 having a reference of that object it prints out the modified list.
In second case the first object is inside the second list but you changes the variable pointer to another object but the second list still contains the first objects reference therefore it did not change.

Answered By: tarunjarvis5
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.