Python ijk乘法,为什么我们使用以下赋值符号或代码行?

时间:2018-07-24 19:25:11

标签: python matrix-multiplication

我正在尝试实现两个2 * 2矩阵的简单乘法。我遇到了以下代码。

def ikjMatrixProduct(A, B):
    n = len(A)
    C = [[0 for i in range(n)] for j in range(n)]
    for i in range(n):
        for k in range(n):
            for j in range(n):
                C[i][j] += A[i][k] * B[k][j]
    return C

我们为什么要使用此分配: C = [第3行中的[[0表示范围(n)中的i,0]表示范围(n)中的j]

我以前从未见过这样的作业。可以请别人解释一下。

我自己的代码抛出错误,因为我使用了c = []并且此代码有效。

1 个答案:

答案 0 :(得分:1)

正如Merlin1896所说,C = [[0 for i in range(n)] for j in range(n)]创建一个2D列表,即n列表的列表,每个内部列表包含n零。列表为空,直到您将其填满为止。如果C是一个空列表,则无法执行C[i][j] += A[i][k] * B[k][j],因为C[i][j]还不存在。

一种更快的初始化矩阵的方法是

C = [[0] * n for j in range(n)]

在最里面的列表上使用列表乘法是安全的,因为它们包含不可变的整数。但是在外部列表上是安全的,因为列表是可变的。进行C = [[0] * n] * n会使外部列表引用一个列表对象。例如,

n = 4
C = [[0] * n] * n
print(C)
C[0][0] = 1
print(C)

输出

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

但是,最好重新组织代码,以免不必用零填充列表。我们可以通过更改循环顺序,使k循环成为最内部循环来实现。然后,我们可以将内置的sum函数与生成器表达式一起使用。

def ikjMatrixProduct(A, B):
    n = len(A)
    C = []
    for i in range(n):
        row = []
        for j in range(n):
            row.append(sum(A[i][k] * B[k][j] for k in range(n)))
        C.append(row)
    return C

我们可以将其转化为列表理解,尽管许多人认为三重嵌套的列表理解/生成器表达式不是很可读。 ;)

def ikjMatrixProduct(A, B):
    nrange = range(len(A))
    return [[sum(A[i][k] * B[k][j] for k in nrange) for j in nrange] for i in nrange]