Python 列表模拟矩阵出错误

问题很简单,只要意识到怎么回事就能解决。

# 目标:实现矩阵,然后尝试改变矩阵坐标为(i, j)的元素的值

# 实现:用列表作为行来模拟矩阵

def initMatrix(rank=3):
    """
	假定矩阵是方阵,秩(rank)默认为3
	"""
    matrix = []
    row = [0] * rank
    for i in range(rank):
        matrix.append(row)
    return matrix


def update(matrix, t):
    '''
	假定 matrix 是一个矩阵, t 是一个 tuple , t = (i, j)
	将第 i 行 第 j 列的元素值更新为1
	'''
    matrix[t[0] - 1][t[1] - 1] = 1
    return


def printMatrix(matrix):
    '''假定 matrix 为一个矩阵'''
    for row in matrix:
        print(row)
    print()
    return


def main():
    matrix = initMatrix()
    printMatrix(matrix)
    update(matrix, (2, 2))
    printMatrix(matrix)
    return

main()

# 输出
[0, 0, 0]
[0, 0, 0]
[0, 0, 0]

[0, 1, 0]
[0, 1, 0]
[0, 1, 0]

本意是让 (2, 2) 位置的元素改为 1,但结果是每一行的第 2 个元素都变成了 1 。
原因在于创建矩阵时:

for i in range(rank):
	matrix.append(row)

这样一来,矩阵的每一行都是指向同一个列表的指针。
可用如下方法测试:

def printMatrix(matrix):
	for row in matrix:
		print(id(e))
	return

你会发现,每一行的id都是一样的。也就是说,它们是同一个东西。
只要对任一行的元素作操作,就相当于对每一行都进行了操作。所以这种直接 matrix.append(row)是行不通的。

def initMatrix(rank=3):
    """
	假定矩阵是方阵,秩(rank)默认为3
	"""
    matrix = []
    row = [0] * rank
    for i in range(rank):
        matrix.append(row.copy())  # 用浅拷贝替代
    return matrix

使用列表的乘法同样有上述问题

def initMatrix(r, c):
    """
    :param r:row of matrix wanted
    :param c:column of matrix wanted
    :return: a 2-d array, regarded as a matrix
    """
    matrix = [[0] * c] * r
    return matrix


def updateMatrix(matrix, i, j, new_value):
    """
    :param matrix: a 2-d list regarded as matrix to be updated
    :param i: row of position to update
    :param j: column of position to update
    :param new_value to replace old value
    :return: updated matrix
    """
    matrix[i-1][j-1] = new_value
    return matrix


matrix = initMatrix(3, 5)
print(matrix)
print(type(matrix))
matrix = updateMatrix(matrix, 3,5,100)
print(matrix)

for e in matrix:
    print(id(e))
#输出如下:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
<class 'list'>
[[0, 0, 0, 0, 100], [0, 0, 0, 0, 100], [0, 0, 0, 0, 100]]
2302841322304
2302841322304
2302841322304
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值