Matrix Multiplication in Python
Multiply matrices in Python the right way. Compare @, np.dot, np.matmul, and pure-Python loops with runnable examples — no setup required.
Try it yourself
Run this code directly in your browser. Click "Open in full editor" to experiment further.
Click Run to see output
Or press Ctrl + Enter
How it works
Matrix multiplication is the workhorse of scientific computing — it's what powers neural networks, 3D graphics, physics simulations, and pretty much every recommendation algorithm you've ever used. Getting it right in Python comes down to one simple choice: use NumPy and the @ operator.
What Matrix Multiplication Actually Is
If you have a matrix A of shape (m, n) and a matrix B of shape (n, p), then A @ B produces a new matrix of shape (m, p). Every entry (i, j) in the result is the dot product of row i from A with column j from B.
The only hard rule: the inner dimensions must match. A 3×4 matrix can multiply a 4×2 matrix (the 4s line up), but it cannot multiply a 5×2.
The Four Ways to Multiply
| Approach | Syntax | When to use |
|---|---|---|
@ operator | A @ B | Default choice. Cleanest and most readable. |
np.matmul | np.matmul(A, B) | Same as @. Use inside other expressions if you prefer function form. |
np.dot | np.dot(A, B) | Older API. For 2D arrays it's identical to @, but it behaves differently for 1D and higher-D arrays — easy to trip on. |
| Pure Python loops | triple for loop | Never. Hundreds of times slower. Useful only for understanding what's happening. |
If you remember nothing else, remember this: use `@`.
The Element-Wise Trap
This one bites everyone exactly once:
A * B # element-wise — multiplies positions individually
A @ B # matrix multiplication — dot products of rows and columnsFor two 2×2 matrices these give completely different answers. If your gradient explodes or your output looks wrong, this is the first thing to check.
Why NumPy Crushes Plain Python
A pure-Python triple loop for matrix multiplication does the math correctly but spends most of its time on Python-level overhead — every multiplication and addition goes through the interpreter. NumPy hands the work off to BLAS (Basic Linear Algebra Subprograms), a hyper-tuned library written in C and Fortran that uses CPU vector instructions and cache-aware algorithms.
For a 200×200 multiply, the difference is typically 100-1000×. Scale up to 1000×1000 and the pure-Python version simply doesn't finish.
Common Shapes You'll Actually Use
(batch, features) @ (features, output) — a single layer of a neural network(3, 3) @ (3, n) — applying a rotation/transformation to n 3D pointsX.T @ X — the Gram matrix, the foundation of linear regression's normal equationA @ x where x is 1D — solving systems, projecting vectorsQuick Gotchas
A.shape and B.shape. The inner two numbers must match.A.T (no parentheses, no method call).np.eye(n). A @ np.eye(n) == A.Run the snippet above and you'll see the same multiplication done four ways, the element-wise trap, and a head-to-head speed test that explains in one print statement why the rest of the scientific Python world is built on NumPy.
Related examples
NumPy Array Operations in Python
Learn NumPy basics in Python! A fun and easy guide to super-fast arrays, matrices, and data science math without using slow for-loops.
Linear Regression in Python (from Scratch)
Build linear regression in Python from scratch with NumPy, then compare to scikit-learn. Step-by-step math, runnable code, and a real plotted fit.
Fourier Transform (FFT) in Python
Learn the Fast Fourier Transform in Python. Decompose signals into frequencies with numpy.fft, plot the spectrum, and filter noise — all runnable in your browser.