C. Brooks C. Brooks - 5 months ago 14
Python Question

Python: iterating and modifying nested lists

I apologize if this question has been asked before, as it seems to be very basic. Unfortunately, when I searched for my question, I could only find other questions asking how to iterate over a list of lists, and none of these questions touched on the specific behavior I am asking about.

I am aware that in python, when you equate two lists, you are not actually copying that list in memory, just creating a new alais pointing to that list in memory. so something like

listA = [1,2,3]
listB = listA
listB[0] = 5
print(listA) #prints [5,2,3]


makes perfect sense to me.

I also know that you can modify mutable types (like lists) in a for loop, while for other types (like integers), you cannot, and must modify the original list. for example

listA = [1,2,3]
listB = [4,5,6]
for Int in listA:
Int +=1
print(listA) #doesn't work, prints [1,2,3]

for List in [listA,listB]:
List[2] = 100
print(listA) #works, prints [1,2,100]


my problem appeared when I tried to combine these two principles. Here is an example of what I tried to do:

x = [1.2345,0.543895,0.0]
y = [2,3,4]
z = [65.34,3.248578493,1.11111]
for coord in [x,y,z]:
rounded_coord = [round(item,3) for item in coord]
coord = rounded_coord
print(x,y,z) #prints unmodified numbers


In this example, 'coord' is a list, and therefore I should be able to modify it, just like listA in my previous examples, but I can't. I have to use enumerate:

x = [1.2345,0.543895,0.0]
y = [2,3,4]
z = [65.34,3.248578493,1.11111]
coordlist = [x,y,z]
for idx,coord in enumerate(coordlist):
coordlist[idx] = [round(item,3) for item in coord]
print(coordlist)


Why doesn't my original attempt work?

Answer Source

'coord' is a list, and therefore I should be able to modify it...

Almost, but not quite. coord is a variable that stores a reference to the each of the original lists in turn per iteration.

rounded_coord is also a variable that stores a reference to a new list.

Now, doing coord = rounded_coord will make the variable coord point to the same reference as rounded_coord. Meaning, the original contents of coords will remain unchanged while the reference that coord points to changes.

Example:

>>> x = [1, 2, 3, 4, 5]
>>> for l in [x]:
...    print(id(l))
...    new_l = [1]
...    l = new_l
...    print(id(l))
...    
4309421160
4309421592

By the way, id prints a 10 digit number representing the reference a variable points to. You can see that at the start vs at the end, the reference stored in l changes.