Home > OS >  Assignment of variable to list using indexing
Assignment of variable to list using indexing

Time:06-27

The following is a simple function:

def func(first):
         third = first[0]
         first[0][0] = 5
         print(third)

first = [[3,4]]
func(first)

I was expecting the output to be [3,4] but instead, it's supposed to be [5,4]. I thought that during the assignment of the variable "third" in the first line, the right-hand side of "first[0]" had already been evaluated to give [3,4] and thus, third would stay as this value for the rest of the function execution steps.

Edit:

I now understand why the above function works the way it does. The variable third references the list within first and thus, when that changes, third will also change. I now have one more question:

What about referencing a slice of a list, instead of a specific index?

def func(first):
         third = first[0][0:2]
         first[0][0] = 5
         print(third)

first = [[3,4]]
func(first)

Does this method of referencing now create a new list that third is referenced to?

CodePudding user response:

Your code reads:

def func(first):
         third = first[0]
         first[0][0] = 5
         print(third)

first = [[3,4]]
func(first)

What's happening is this:

  • In func(), the argument first contains a reference to a list of lists with value [[3,4]].
  • After the assignment to third, third contains a reference to the list [3,4] at position 0 in the list referenced by first. No new list object has been created and no copy of a list has taken place, rather a new reference to the existing list has been created and stored in the variable third.
  • In the line first[0][0] = 5, the item at position 0 in the list [3,4] is updated so that the list is now [5,4]. Note that the list [3,4] that was modified is an element of the list of lists referenced by first, and it is also the one referenced by third. Because the object (namely, the list) that is referenced by third has now been modified, any use of this reference to access the list (such as print(third)) will reflect its updated value, which is [5,4].

UPDATE:

The code for your updated question is:

def func(first):
         third = first[0][0:2]
         first[0][0] = 5
         print(third)

first = [[3,4]]
func(first)

In this case, the assignment third = first[0][0:2] takes a slice of the list [3,4] at position 0 in the list of lists referenced by first. Taking a slice in this way creates a new object which is a copy of the subsequence indicated by the arguments specified in the square brackets, so after the assignment, the variable third contains a reference to a newly created list with value [3,4]. The subsequent assignment first[0][0] = 5 updates the value of the list [3,4] in position 0 of the list of lists referenced by first, with the result that the value of the list becomes [5,4], and has no effect on the value of third which is an independent object with value [3,4].

Importantly (and potentially confusingly), slice notation used on the left-hand side of an assignment works very differently. For example, first[0][0:2] = [5,4] would change the contents of the list first[0] such that the elements in index 0 and 1 are replaced by [5,4] (which in this case means the value of the list object would be changed from [3,4] to [5,4], but it would be the same object).

CodePudding user response:

A variable identifies a memory location. If the contents of the memory location is mutable like a list, the contents are changed by code. All names that identify that location will reflect the change. If the contents are immutable like an integer the name will be assigned a new memory location. x = 5 y =5, x and y point to the same memory location. x = 6 y will still point to the location containing 5. x will point to the location containing 6.

def func(first):
    third = first[0]
    print(f'{id(first[0])=}  {id(third)=}')  # They are the same list. 
    # Name points to same address. So changing contents of memory.
    first[0][0] = 5
    print(third)


first = [[3, 4]]
func(first)

Output

id(first[0])=2652914318144  id(third)=2652914318144
[5, 4]
  • Related