为什么python中的'for'循环会更改未引用的列表?

时间:2010-12-15 23:06:52

标签: python list variables for-loop scope

我正在编写一个py脚本,它从csv文件中读取行,操纵它们并将它们放回原处。到目前为止,我有csv列出转换工作。

我遇到的问题是当我遍历临时列表时,for循环会更改所有临时列表,而不仅仅是我想要的那个。这是我想说的一个简单的例子。

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

所以上述内容很简单(希望如此)。 (我们假设除了复制列表之外我还想做其他事情。只是想保持简单)。

但现在这是我没有得到的部分。

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

当我想修改子列表中的第一部分并将其保存到新列表'z'时,它也会修改列表t!

这里发生了什么? z,y和t是否指向相同的内存位置?

此外,这里发生了什么?:

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

与上述问题类似,为什么y和t会发生变化?

提前致谢!!

3 个答案:

答案 0 :(得分:7)

Python没有引用。 row是对ly中实际元素的引用。变异row变异该元素,并将其添加到另一个对象中添加原始元素。

答案 1 :(得分:4)

您的三个列表不同,但它们之间只共享两个元素:

>>> y[0] is t[0] is z[0]
True
>>> y[1] is t[1] is z[1]
True

如果is运算符告诉您引用指向同一个对象,则无论您使用哪个引用,都会显示对该对象的更改。

要避免这种情况,请使用copy模块,如果您需要元素的副本:

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

答案 2 :(得分:0)

“z,y和t是否指向相同的内存位置?”

不,但是z [0],y [0]和t [0]是(虽然不称它为内存位置,但这不是C)。您将相同的列表['hi', 'ho']附加到z,y和t。所以它是相同的列表。如果您不希望它是同一个列表,则必须先制作副本。