尝试在一个地方更改时,值列表中的多个位置的值会发生变化

bil*_*kar 3 python matrix

python中的以下代码:

matrix = [[0]*3]*2
matrix[0][1] = 1
Run Code Online (Sandbox Code Playgroud)

看到要改变所有matrix[][1]位置的值,矩阵变为 [[0,1,0],[0,1,0]]代替[[0,1,0],[0,0,0]].

这是变量如何初始化的问题,或者是python中的默认行为.

另外,我如何一次只更改一个值.

mac*_*mac 6

关于乘法运算符如何*在python中的列表上工作,有一些细微之处.

更一般地说,当应用于不可变对象(如整数或字符串)时,它的效果会有所不同,以及它们在应用于列表和字典等可变对象时的效果.

这可能会澄清问题:

>>> l = [0] * 3  #a list of immutable integers
>>> l
[0, 0, 0]
>>> l[0] = 1
>>> l
[1, 0, 0]
>>> l = [[0]] * 3  #a list of mutable lists
>>> l
[[0], [0], [0]]
>>> l[0][0] = 1
>>> l
[[1], [1], [1]]
Run Code Online (Sandbox Code Playgroud)

EDIT(评论中对@lazyr的称赞)在两种情况下,*运算符都会创建一个具有相同标识(内存地址)的对象列表,因此数组中的每个数字(和每个列表)实际上都是同一个对象,但是,不可变类型不能被修改但只能被替换,因此当您尝试为整数数组分配新值时,您将事实上替换整个对象,而列表不是这种情况.上一个示例中的Bulding(请记住该id函数返回对象的内存地址):

>>> m = [1] * 3
>>> id(m[0])
39356344
>>> id(m[1])
39356344
>>> m[1] = 2
>>> id(m[1])
39356320  # new memory addres = different object!
>>> m = [[1]] * 3
>>> id(m[0])
40275408
>>> id(m[1])
40275408
>>> m[1][0] = 2
>>> id(m[1])
40275408  # same memory address = still the same object!
Run Code Online (Sandbox Code Playgroud)

因此,在您的情况下,可能的解决方法是初始化矩阵,如下所示:

>>> matrix = [[0 for i in range(3)] for j in range(2)]
>>> matrix
[[0, 0, 0], [0, 0, 0]]
>>> matrix[0][2] = 1
>>> matrix
[[0, 1, 0], [0, 0, 0]]
Run Code Online (Sandbox Code Playgroud)

另一种 - 更激进的方式 - 将完全转向numpy,这种方法更快,并且从根本上考虑了极快的矩阵和多维向量操作,但它也更难使用.

HTH!

  • 正如我已经理解的那样,事实上*对可变和不可变类型的操作没有区别.在这两种情况下,它都会创建具有相同标识(内存地址)的对象列表.不同之处在于稍后发生的修改:不可变类型不能被修改但只能被替换,因此您只能看到对可变类型的这种影响. (2认同)