NumPy is the foundation everything else stands on. PyTorch tensors, TensorFlow tensors, JAX arrays, and pandas Series — they all share NumPy's API and mental model. The big idea: operate on whole arrays at once instead of looping element by element. That single shift unlocks 10–100× speedups and a much cleaner notation.
ndarray — the core object
A NumPy array (ndarray) is a contiguous block of memory holding values of one type. It has a `shape` (how many elements along each dimension), a `dtype` (float32 / int64 / etc.), and supports element-wise math out of the box. Reshaping, slicing, and broadcasting let you manipulate them with very little code.
Element-wise math (no loops):
a + b adds every element
a * 2 scales every element
a @ b matrix multiplication
a.sum() reduces to a scalar
a.T transposes
a.shape e.g. (3, 4) for a 3×4 matrixWhole arrays at once — the C kernel runs the loop, not Python
Broadcasting — the magic rule
If two arrays have different shapes, NumPy will silently 'stretch' the smaller one along missing axes — as long as dimensions match or are 1. That lets you add a row vector to every row of a matrix in one line, or normalize each column without writing nested loops.
- Create: `np.zeros((3, 4))`, `np.ones`, `np.random.randn`, `np.arange(10)`
- Reshape: `a.reshape(2, 6)`, `a.T` (transpose), `a.flatten()`
- Slice: `a[1:3, :]` selects rows 1-2, all columns
- Reduce: `a.sum()`, `a.mean()`, `a.max()`, `a.argmax()`
- Linear algebra: `a @ b` matmul, `np.linalg.inv(a)` inverse, `np.linalg.norm(a)` length