一个列表意外更改也会改变另一个列表

sod*_*ate 5 python python-2.7

我有一份表格清单

v = [0,0,0,0,0,0,0,0,0]
Run Code Online (Sandbox Code Playgroud)

我在代码中的某个地方

vec=v
vec[5]=5
Run Code Online (Sandbox Code Playgroud)

这既改变vvec:

>>> print vec
[0, 0, 0, 0, 0, 5, 0, 0, 0]
>>> print v
[0, 0, 0, 0, 0, 5, 0, 0, 0]
Run Code Online (Sandbox Code Playgroud)

为什么要v改变?

小智 13

为什么v会发生变化?

vec和v都是指针.编码vec = v时,将v地址分配给vec.因此,在v中更改数据也会"改变"vec.

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

vec = list(v)
Run Code Online (Sandbox Code Playgroud)


sta*_*ack 7

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

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

from copy import deepcopy
vec = deepcopy(v)
Run Code Online (Sandbox Code Playgroud)

或者

vec = v[:]
Run Code Online (Sandbox Code Playgroud)


wp-*_*com 5

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

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


这可能看起来违反直觉。为什么不将复制列表设置为默认行为?考虑情况

def foo():
    my_list = some_function()
    # Do stuff with my_list
Run Code Online (Sandbox Code Playgroud)

您是否不想my_list包含与创建时完全相同的列表some_function,并且不想让计算机花费额外的时间来创建副本。对于大型列表,复制数据可能需要一些时间。因此,Python 不会在赋值时复制列表。



其他注意事项:

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

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

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


小智 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)
Run Code Online (Sandbox Code Playgroud)

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

a:  [10, 3, 4] 140619073542552                                                                                                
b:  [10, 3, 4] 140619073542552                                                                                                
c:  [7, 3, 4] 140619073604136
Run Code Online (Sandbox Code Playgroud)

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