插入到未知维度的矩阵

时间:2017-08-11 12:12:14

标签: python python-3.x matrix multidimensional-array reference

我在编写一个用于处理多维矩阵的Matrix类的setter函数时遇到了麻烦,因为我实现了动态编程算法。

使用嵌套列表存储矩阵。由于维度未知,因此代码背后的想法是使用坐标(索引列表)并在从坐标读取索引时迭代地进入矩阵。

def setField(self, coordinate, value):
    coordinate = coordinate[::-1] # reverse the coordinate so .pop() can be used 
    field = self.matrix
    while len(coordinate) > 1:
        field = field[coordinate.pop()]

    field[coordinate[0]] = value

使用代码:

>>> m = Matrix([3,3,3]) # initialize Matrix of size 3 in all dimensions
>>> m.tolist() # list representation
[[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]
>>> m.setField([1,1,1], 42) # at position [1,1,1] insert 42
>>> m.tolist()
[[[0, 0, 42], [0, 0, 42], [0, 0, 42]], [[0, 0, 42], [0, 0, 42], [0, 0, 42]], [[0, 0, 42], [0, 0, 42], [0, 0, 42]]]

现在麻烦的是,进入矩阵'部分是通过参考矩阵完成的。由于我不明白的原因,变化不仅发生在一个领域(矩阵应该被改变为给定值),而是发生在矩阵表示的每个子列表中。

让我更加困惑的是,以下代码在Python shell中运行得很好:

>>> m = [[0,0],[0,0]]
>>> field = m
>>> field = field[0]
>>> field[1] = 1
>>> m
[[0, 1], [0, 0]]
  • 我在这里做错了什么?
  • 为什么Python表现那样?

编辑/解释

正如答案所指出的,矩阵中的所有子列表实际上都是相同的。

>>> m = Matrix([2,2])
>>> id(m.matrix[0]) == id(m.matrix[1])
True

要避免此行为,必须使用副本。

1 个答案:

答案 0 :(得分:0)

您所看到的问题是因为矩阵的子数组在内存中实际上是相同的,所以修改它们会改变它们。

这就是你正在做的事情:

>>> a = [0, 0]
>>> m = [a, a]
>>> m
[[0, 0], [0, 0]]
>>> m[0][1] = 42
>>> m
[[0, 42], [0, 42]]
>>> id(m[0]) == id(m[1]) # same object in memory
True

这是你想要做的:

>>> a = [0,0]
>>> m = [a.copy(), a.copy()]
>>> m[0][1] = 42
>>> m
[[0, 42], [0, 0]]
>>> id(m[0]) == id(m[1]) # different objects in memory
False

话虽如此,在numpy中做起来容易得多:

>>> import numpy as np
>>> m = np.zeros((2, 2))
>>> m[0,1] = 42
>>> m
array([[  0.,  42.],
       [  0.,   0.]])