1

我知道列表别名是 Python 中的一个问题,但我无法找到解决方法。

def zeros(A):
    new_mat = A
    for i in range(len(A)):
        for j in range(len(A[i])):
            if A[i][j]==0:
                for b in range(len(A)):
                    new_mat[b][j] = 0
            else:
                new_mat[i][j] = A[i][j]
    return A

即使我根本不更改 A 的值,当我返回 A 时,它仍然会被修改:

>>> Matrix = [[1,2,3],[5,0,78],[7,3,45]]
>>> zeros(Matrix)
[[1, 0, 3], [5, 0, 78], [7, 0, 45]]

这个列表有别名吗?如果是这样,你如何修改二维数组的元素而不发生混叠?非常感谢<3。

4

4 回答 4

3

new_mat = A不创建新矩阵。你只是给你也知道的对象一个新名字A。如果它是数字列表的列表,您可能希望使用copy.deepcopy创建完整副本,如果它是一个 numpy 数组,您可以使用copy方法。

于 2015-02-01T23:43:23.127 回答
1
new_mat = A[:]

这会创建列表的副本,而不仅仅是引用它。试试看。

[:]只是从头到尾指定一个切片。例如,您可以[1:]从元素 1 到结尾,或者从[1:4]元素 1 到 4。查看有关此的列表切片。

于 2015-02-01T23:41:00.570 回答
1

这可能对其他人有帮助。就这样做。

import copy

def zeros(A):
    new_mat = copy.deepcopy(A)
于 2017-10-27T03:37:16.487 回答
1

快速解释

如果您希望 A 成为原始矩阵,您的函数应该是这样的。只需使用np.copy()功能

def zeros(A):
    new_mat = np.copy(A) #JUST COPY IT WITH np.copy() function
    for i in range(len(A)):
        for j in range(len(A[i])):
            if A[i][j]==0:
                for b in range(len(A)):
                    new_mat[b][j] = 0
            else:
                new_mat[i][j] = A[i][j]
    return A

详尽的解释

假设我们不希望 numpy ndarraya有别名。例如,a当我们取(例如)它的一个切片时,我们希望防止更改它的任何值,我们将这个切片分配给b然后我们修改 b 的一个元素。我们要避免这种情况:

import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
b = a[0]
b[2] = 50
a
Out[]: 
array([[ 1,  2, 50],
       [ 4,  5,  6],
       [ 7,  8,  9]])

现在您可能认为将 numpy-ndarray 对象视为列表对象可能会解决我们的问题。但它也不起作用:

%reset #delete all previous variables
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
b = a[:][0] #this is how you would have copied a slice of "a" if it was a list
b[2] = 50
a
Out[]: 
array([[ 1,  2, 50], #problem persists
       [ 4,  5,  6],
       [ 7,  8,  9]])

在这种情况下,如果您将 numpy 数组视为与 python 列表不同的对象,问题就会得到解决。为了复制 numpy 数组,您不能这样做copy = name_array_to_be_copied[:],但是copy = np.copy(name_array_to_be_copied). 因此,这将解决我们的别名问题:

%reset #delete all previous variables
import numpy as np
a = np.array([[1,2,3],[4,5,6],[7,8,9]])
b = np.copy(a)[0] #this is how you copy numpy ndarrays. Calling np.copy() function
b[2] = 50
a
Out[]: 
array([[1, 2, 3], #problem solved
       [4, 5, 6],
       [7, 8, 9]])

PS 注意这个zeros() 功能。即使在修复了别名问题之后,您的函数也不会将 new_matrix 中的列转换为 0,这些列在矩阵 A 的同一列中至少有一个零(这是我认为您希望通过查看错误报告的输出来完成的你的函数[[1, 0, 3], [5, 0, 78], [7, 0, 45]],因为它实际上产生[[1,0,3],[5,0,78],[7,3,45]])。如果你愿意,你可以试试这个:

def zeros_2(A):
    new_mat = np.copy(A)
    for i in range(len(A[0])): #I assume each row has same length.
        if 0 in new_mat[:,i]:
            new_mat[:,i] = 0
    print(new_mat)
    return A
于 2018-03-27T16:09:43.060 回答