Why does a 'for' loop in python change unreferenced lists?
I'm working on a py script which reads in lines from a csv file, manipulates them, and puts them back out. So far I have the csv to list conversion working.
The problem I am having is when I iterate over the temporary lists, the for loops change ALL the temp lists, instead of just the one I want. Here is a simple example of what I'm trying to say.
>>> l = [['hi', 'ho'],['no', 'go']]
>>> t = []
>>> y = []
>>>
>>> for row in l:
... row[0] = '123'
... y.append(row)
... t.append(row)
...
>>> y
[['123', 'ho'], ['123', 'go']]
>>> t
[['123', 'ho'], ['123', 'go']]
So the above is straightforward (hopefully). (Let's assume I want to do other things besides just copy the list l.开发者_Go百科 Just wanted to keep it simple).
But now here is the part I don't get.
>>> z = []
>>> for row in y:
... row[0] = 'xxxx'
... z.append(row)
...
>>> z
[['xxxx', 'ho'], ['xxxx', 'go']]
>>> t
[['xxxx', 'ho'], ['xxxx', 'go']]
>>> y
[['xxxx', 'ho'], ['xxxx', 'go']]
When I want to modify the first part in the sub-lists, and save it to a new list 'z', it modifies list t as well!
What's going on here? Are z, y and t pointing to the same memory location?
Also, what's happening here?:
>>> for rowx in y:
... rowx[0] = 'x55x'
... z.append(rowx)
...
>>> z
[['xxxx', 'ho'], ['x55x', 'go'], ['x55x', 'go'], ['x55x', 'go']]
>>> t
[['xxxx', 'ho'], ['x55x', 'go']]
>>> y
[['xxxx', 'ho'], ['x55x', 'go']]
Similar to the above question, why are y and t getting changed?
Thanks in advance!!
Python has nothing but references. row
is a reference to the actual element within l
or y
. Mutating row
mutates that element, and adding it to another object adds the original element.
Your three lists are different, but there are only two elements shared between them:
>>> y[0] is t[0] is z[0]
True
>>> y[1] is t[1] is z[1]
True
If the is
operator tells you that your references point to the same object, then changes to the object will appear no matter which reference you use.
To avoid this, use the copy module if you want a copy of the elements:
>>> import copy
>>> a = copy.deepcopy(y)
>>> a
[['xxxx', 'ho'], ['xxxx', 'go']]
>>> a[0] is y[0]
False
>>> a[0][0] = 'copy!'
>>> y
[['xxxx', 'ho'], ['xxxx', 'go']]
"Are z, y and t pointing to the same memory location?"
No, but z[0], y[0] and t[0] are (although don't call it memory locations, this is not C). You are appending the same list ['hi', 'ho']
to both z, y and t. So it's the same list. If you don't want it to be the same list, you have to make a copy first.
精彩评论