功能中的矩阵视图没有副作用

时间:2012-02-23 18:04:47

标签: python numpy

修改:我发现问题归结为:

如果您运行此代码:

A = ones((10,4))
view = A[:,1]
view.fill(7)
A

A = ones((10,4))
view = A[:,1:3]
view.fill(7)
A

你会看到A的列改变

如果你运行:

A = ones((10,4))
view = A[:,(1,2)]
view.fill(7)
A

对A没有副作用。这种行为是故意还是错误?

我有一个函数来计算我必须旋转矩阵中x,y点的某些列的量。该函数只接受一个输入 - 矩阵垫:

def rotate(mat):

在函数中,我创建视图以便更轻松地使用每个部分:

rot_mat = mat[:,(col,col+1)]

然后,我计算一个旋转角度并将其应用回我之前创建的视图:

rot_mat[row,0] = cos(rot)*x - sin(rot)*y
rot_mat[row,1] = sin(rot)*x + cos(rot)*y

如果我在程序的主体中执行此操作,对rot_mat视图的更改将传播到原始矩阵mat。当我把它变成一个函数时,视图停止对原始矩阵产生副作用。这是什么原因,有没有办法绕过它?我还应该注意,它并没有改变函数本身。最后,我只是尝试返回垫子,但没有做出任何改变。

功能的完整代码:

def rotate(mat):
    # Get a reference shape
    ref_sh = 2*random.choice(range(len(filelist)))
    print 'Reference shape is '
    print (ref_sh/2)
    # Create a copy of the reference point matrix
    ref_mat = mat.take([ref_sh,ref_sh+1],axis=1)
    # Calculate rotation for each set of points
    for col in range(len(filelist)):
        col = col * 2 # Account for the two point columns
        rot_mat = mat[:,(col,col+1)]
        # Numerator = sum of wi*yi - zi*xi
        numer = inner(ref_mat[:,0],rot_mat[:,1]) - inner(ref_mat[:,1],rot_mat[:,0])
        # Denominator = sum of wi*xi + zi*yi
        denom = inner(ref_mat[:,0],rot_mat[:,0]) + inner(ref_mat[:,1],rot_mat[:,1])
        rot = arctan(numer/denom)
        # Rotate the points in rot_mat.  As it's a view of mat, the effects are
        # propagated.
        for row in range(num_points):
            x = rot_mat[row,0]
            y = rot_mat[row,1]
            rot_mat[row,0] = cos(rot)*x - sin(rot)*y
            rot_mat[row,1] = sin(rot)*x + cos(rot)*y
    return mat

1 个答案:

答案 0 :(得分:0)

执行view = A[:,(1,2)]时,您正在使用高级索引(Numpy manual: Advanced Indexing),这意味着数组返回副本,而不是视图。它是高级的,因为您的索引对象是一个“包含至少一个序列”的元组(序列是元组(1,2))。您的案例中的总显式选择对象obj将等于(slice(None), (1,2)),即A[(slice(None), (1,2))]返回与A[:,(1,2)]相同的内容。

正如上面的larsmans所暗示的那样,__getitem____setitem__似乎对高级索引的行为有所不同,这是有道理的,因为为副本赋值不会有用(副本不会被存储)