As Merlin1896 said, C = [[0 for i in range(n)] for j in range(n)]
creates a 2D list, that is, a list of n
lists, with each inner list containing n
zeros. A list is empty until you fill it with something. You can't do C[i][j] += A[i][k] * B[k][j]
if C is an empty list, since the C[i][j]
don't exist yet.
A quicker way to initialize your matrix is
C = [[0] * n for j in range(n)]
It's safe to use list multiplication on the innermost lists, since they contain integers, which are immutable. But it's not safe on the outer lists because lists are mutable. Doing C = [[0] * n] * n
makes the outer lists references to the one list object. Eg,
n = 4
C = [[0] * n] * n
print(C)
C[0][0] = 1
print(C)
output
[[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]]
However, it's better if we reorganize the code so that we don't have to pre-fill the lists with zeros. We can do that by changing the loop order, making the k
loop the innermost. Then we can use the built-in sum
function with a generator expression.
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
We could turn that into a list comprehension, although many would argue that a triply-nested list comprehension / generator expression is not very readable. ;)
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]