Matrices in Python: Rectangular Arrays, Equality, and Element-Wise Operations
Part 1 of 5 in Matrix Algebra: Systems, Pivots, and Inverses
Matrices in Python
A matrix is a rectangular array of numbers arranged in m rows and n columns — conventionally written as an m × n matrix. In mathematics:
In Python, the natural representation is a list of lists: the outer list holds rows, each inner list is one row’s values. A[i][j] picks row i, column j (0-indexed).
This post covers three foundational operations — all in pure Python, no NumPy required:
- Equality — when two matrices are “the same”
- Element-wise addition and subtraction — cell-by-cell arithmetic with dimension guards
- Scalar multiplication — scaling every element by one number
Matrices and equality
Two matrices A and B are equal if and only if:
- They have the same number of rows (both m),
- Each corresponding row has the same length (both n), and
A[i][j] == B[i][j]for every pair (i, j).
Both shape and values must match — a matrix with different dimensions is never equal to another, regardless of what it contains.
The code checks all three conditions:
def matrix_equal(A, B):
if len(A) != len(B): # row count?
return False
for i in range(len(A)):
if len(A[i]) != len(B[i]): # column count per row?
return False
for j in range(len(A[i])):
if A[i][j] != B[i][j]: # element value?
return False
return True
The three comparisons show the rule: matching shape + matching values produces equality, while a mismatch at either layer produces False.
Element-wise addition and subtraction
For two m × n matrices A and B, element-wise operations produce:
This is only defined when both matrices share the same dimensions — unlike array broadcasting in NumPy, plain Python lists need an explicit shape guard:
def matrix_add(A, B):
shA, shB = shape(A), shape(B)
if shA is None or shB is None or shA != shB:
return None # dimension mismatch — not just silently wrong
rows, cols = shA
return [[A[i][j] + B[i][j] for j in range(cols)]
for i in range(rows)]
The third case — adding a 2×3 matrix to a 2×2 matrix — produces None. That’s the guard doing its job: it prevents producing garbage by rejecting inputs that don’t form a valid operation.
Scalar multiplication
Here’s where scalar multiplication differs from addition and subtraction. For any scalar k and any matrix A:
There is no dimension constraint — you can scale any matrix by any number:
def scalar_multiply(A, k):
rows = len(A)
cols = len(A[0]) if rows else 0
return [[k * A[i][j] for j in range(cols)]
for i in range(rows)]
A negative scalar flips signs, and a fractional scalar like 3.5 smoothly interpolates — every element gets the same treatment.
Takeaway
A matrix in Python is a list of equal-length lists. Equality demands shape and values match. Addition and subtraction require matching shapes as a pre-condition; scalar multiplication works on anything, any time. The pattern behind all three operations is the same: iterate cell by cell, do your math, collect into a new list of lists.