更改一个列表也会意外更改另一个列表 [重复]

Changing one list unexpectedly changes another, too [duplicate]

提问人:sodiumnitrate 提问时间:4/22/2015 最后编辑:wjandreasodiumnitrate 更新时间:9/22/2023 访问量:42641

问:

我有一个表格列表

v = [0,0,0,0,0,0,0,0,0]

在我做的代码中的某个地方

vec=v
vec[5]=5

这改变了两者:vvec

>>> print vec
[0, 0, 0, 0, 0, 5, 0, 0, 0]
>>> print v
[0, 0, 0, 0, 0, 5, 0, 0, 0]

为什么会改变?v

评论

1赞 kpie 4/22/2015
值得注意的是,这种行为不仅限于列表,也可以用 dict 对象观察到,如果它们是可变的,也会在元组上观察到。

答:

5赞 hostingutilities.com 4/22/2015 #1

Python 将两个列表指向同一个内存位置。vec = v

要复制列表,请使用vec = v[:]


这一切似乎都有悖常理。为什么不将复制列表作为默认行为呢?考虑情况

def foo():
    my_list = some_function()
    # Do stuff with my_list

难道您不想包含与创建的完全相同的列表,并且不让计算机花费额外的时间创建副本吗?对于大型列表,复制数据可能需要一些时间。由于这个原因,Python 不会在赋值时复制列表。my_listsome_function



其他注意事项:

  • 如果您熟悉使用指针的语言。在内部,在生成的汇编语言中,只是引用内存中列表开始的地址的指针。vecv

  • 其他语言已经能够通过使用写入时复制来克服我提到的障碍,它允许对象共享内存,直到它们被修改。不幸的是,Python 从未实现过这一点。

  • 有关复制列表或执行深层复制的其他方法,请参阅分配后列表意外更改。为什么会这样,我该如何预防?

10赞 stackattack 4/22/2015 #2

因为 v 指向的列表与 vec 在内存中的列表相同。

如果你不想拥有它,你必须做一个

from copy import deepcopy
vec = deepcopy(v)

vec = v[:]

评论

1赞 Padraic Cunningham 4/22/2015
您不需要浅表的深层副本
41赞 Erez Haim 4/22/2015 #3

为什么 v 会改变?

vec和都是参考。v

编码时,将地址分配给 。 因此,更改数据也会“更改”。vec = vvvecvvec

如果要使用两个不同的数组,请使用:

vec = list(v)
1赞 kpie 4/22/2015 #4

你可以使用

vec=v[:] #but

“Alex Martelli(至少在2007年)对此的看法是,这是一种奇怪的语法,使用它是没有意义的。 ;)(在他看来,下一个更具可读性)。

vec=list(v)

我的意思是这是埃雷兹的链接......“如何在Python中克隆或复制列表?"

5赞 Dhananjay 8/28/2015 #5

运行这段代码,你就会明白为什么变量 v 会发生变化。

a = [7, 3, 4]
b = a
c = a[:]
b[0] = 10
print 'a: ', a, id(a)
print 'b: ', b, id(b)
print 'c: ', c, id(c)

此代码在我的解释器上打印以下输出:

a:  [10, 3, 4] 140619073542552                                                                                                
b:  [10, 3, 4] 140619073542552                                                                                                
c:  [7, 3, 4] 140619073604136

如您所见,列表 a 和 b 指向相同的内存位置。然而,列表 c 是完全不同的内存位置。可以说变量 a 和 b 是同一列表的别名。因此,对变量 a 或 b 所做的任何更改也将反映在另一个列表中,但不会反映在列表 c 中 希望这有帮助!:)