5.4.3 · D1Scientific Computing (Python)

Foundations — Indexing and slicing — basic, boolean masking, fancy indexing

2,338 words11 min readBack to topic

This page defines every symbol and idea the parent note leans on, from absolute zero. Read it top to bottom — each block only uses words already built above it.


0. The very first picture: numbers in a row

Before any code, picture a row of numbered boxes. Each box holds one number. The label under each box is its index — its position, counting from 0, not 1.

Figure — Indexing and slicing — basic, boolean masking, fancy indexing

WHY start at 0? Because the index secretly means "how many boxes do I step past the start?" The first box needs zero steps, so it is index 0. Keep that "steps past the start" meaning — it returns when we meet strides.

Look at figure s01: the blue labels on top are the normal indices 0..4; the yellow labels underneath are the negative indices -5..-1. Both point at the same boxes — two names for one address.


1. The array = data + a recipe (shape, strides, dtype)

The parent note says an array is "numbers laid out in memory, plus a recipe (shape + strides)." Let's earn every word of that.

WHY does NumPy bother with a separate recipe instead of just a list? Because the actual numbers sit in one flat strip of memory. The recipe reinterprets that flat strip as a row, a grid, or a cube — without moving a single number. That single fact is the seed of "view vs copy" later. See NumPy arrays — shape, strides, dtype.

Figure — Indexing and slicing — basic, boolean masking, fancy indexing

In figure s02: the bottom bar is the flat memory strip (the real data). The top grid is what you see as a 3×4 array. The arrows show that "move one column right" = step 1 in memory, but "move one row down" = step 4 in memory (skip a whole row). Those step-sizes are the strides.


2. The colon : and the slice recipe start:stop:step

The parent's first tool is a[start:stop:step]. Three new symbols hide in there: the colon, and the three numbers around it.

WHY is stop excluded? Because of the "steps past the start" meaning of an index: start up to but not including stop makes the length come out as a clean subtraction, stop - start (when step=1). No off-by-one bookkeeping.

Figure — Indexing and slicing — basic, boolean masking, fancy indexing

Figure s03 walks a[1:8:2]: green ring on box 1 (start), red stop-line just before box 8 (never taken), yellow jumps of size 2. Collected boxes: 1, 3, 5, 7.


3. Two dimensions: rows, columns, and the comma

The parent writes A[1, 2] and A[0:2, 1:3]. The comma is the new symbol.

WHY do we need it? A grid has two independent addresses. Without the comma NumPy couldn't tell "row 1" from "column 1". Each slot between commas can itself be a single index or a full start:stop:step slice.

Recall Why

A[:, -1] is the last column : on the left = all rows. -1 on the right = last column. Together: the last column of every row. Answer ::: it grabs index -1 (last box) from every single row, giving one value per row.


4. True / False — the language of masks

Section 2 of the parent uses a boolean array. New idea: a value that is only ever True or False.

WHY does the topic need booleans? Because a condition like "is this number positive?" answers yes or no for each box. Collect those answers and you get a stencil telling NumPy which boxes to keep.

Figure — Indexing and slicing — basic, boolean masking, fancy indexing

Figure s04: top row is the data, middle row is the boolean stencil made by a > 0 (green ✓ = True, red ✗ = False), bottom is what "falls through the holes" — the kept values, gathered into a new shorter strip.


5. Lists of positions — the fancy-index shopping list

Section 3 passes a[[i0, i1, i2]] — a list of integers. New symbols: the inner square brackets [...] and the idea of a position list.

WHY allow a list of positions when we already have slices? Because a slice can only walk in a regular rhythm (fixed step). A list can pick boxes in any order and even repeat them — things a rhythm can never do. That is the whole point of fancy indexing.


6. View vs Copy — the payoff of Section 1's recipe

Now that "recipe" and "flat strip" exist, the parent's headline distinction is easy.

WHY does a slice give a view but a mask/list gives a copy? A slice keeps a regular rhythm, so a single start + step recipe still describes it — no numbers need moving. A mask or list picks boxes scattered irregularly; no single rhythm can describe them, so NumPy must gather them into a fresh strip. See Views vs Copies — memory model.


Prerequisite map

Boxes in a row with index 0..n-1

Negative index counts from end

Recipe: shape + strides + dtype

One flat strip in memory

Colon slice start:stop:step

Ceiling rounds up = element count

Comma separates row and column

Boolean True or False per box

Elementwise and or not

List of positions = shopping list

View shares memory vs Copy gathers

Indexing and slicing

The topic sits at the bottom because it needs every foundation above it. Missing any one is where beginners get stuck. Related deeper notes: Broadcasting, Vectorization — replacing Python loops, np.where and conditional selection, Pandas .loc / .iloc indexing, and the parent indexing overview.


Equipment checklist

Cover the right side and test yourself — you are ready for the parent note only when each is instant.

What does index 0 refer to, and why?
The first box; the index means "how many boxes past the start", and the first is zero steps past.
What box does index -2 point to?
The second-to-last box (count backwards from the right edge).
Name the three parts of the array recipe.
shape (size per direction), strides (memory steps to the next box), dtype (kind of number).
In a[start:stop:step], is stop included?
No — you stop just before stop, so the count subtracts cleanly.
What does the ceiling do?
Rounds x up to the next whole number (a partial last jump still lands on a real box).
How many elements does a[1:8:2] give?
→ boxes 1,3,5,7.
What does the comma do inside A[1, 2]?
Separates directions: left is the row, right is the column.
What does a > 0 produce?
A boolean array (same shape) with True where the box is positive.
Why use &/|/~ instead of and/or/not in a mask?
They answer per box; the English words demand a single yes/no and error on an array.
What can a fancy-index list do that a slice cannot?
Pick boxes in any order and repeat them (a slice only marches in a fixed rhythm).
Why is a slice a view but a mask/list a copy?
A slice is a regular rhythm describable by start/step (share memory); scattered picks must be gathered into a fresh strip.