100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Python

Array Indexing and Slicing

NumPy supports basic slicing, fancy (array) indexing, and boolean masking, each with distinct rules about whether the result is a view or a copy.

NumPy FoundationsBeginner9 min readJul 8, 2026
Analogies

Array Indexing and Slicing

NumPy extends Python's slice syntax to multiple dimensions and adds two powerful mechanisms unavailable on plain lists: fancy indexing (indexing with an array or list of positions) and boolean masking (indexing with a boolean array). Each mechanism has different semantics for whether the returned array shares memory with the original — a distinction that matters enormously for both correctness and performance.

🏏

Cricket analogy: Selecting specific overs like [2, 5, 9] from a season's ball-by-ball array (fancy indexing) or filtering deliveries where runs > 4 (boolean masking) go beyond what a plain Python list of scores could do, and each has different memory-sharing rules that matter for correctness.

Basic Slicing Returns a View

Slicing with start:stop:step syntax, e.g. arr[1:4] or arr[:, 2], returns a view: a new ndarray object pointing at the same underlying memory buffer as the original, just with different shape/stride metadata. No data is copied, which makes slicing extremely cheap, but it also means that modifying the sliced view mutates the original array. If you need an independent copy, call .copy() explicitly.

🏏

Cricket analogy: Slicing overs[1:4] from a full innings array returns a view sharing the same memory as the original scorecard, so editing a value in the sliced overs also silently changes the original innings unless you call .copy() first.

Fancy Indexing and Boolean Masking Return Copies

In contrast, fancy indexing — arr[[0, 2, 4]] or arr[rows, cols] with array/list indices — and boolean masking — arr[arr > 5] — always return a new array with copied data, because the selected elements are not contiguous in general and cannot be represented as a simple view (a stride pattern). This is why chained assignment like arr[arr > 5][0] = 100 silently fails to modify arr: the boolean mask creates a temporary copy, and the assignment happens on that copy.

🏏

Cricket analogy: Selecting scores[[0, 2, 4]] (fancy indexing) or scores[scores > 50] (boolean masking) for a batter's half-centuries always returns a new copied array, which is why chained assignment like scores[scores > 50][0] = 100 silently fails to update the original.

python
import numpy as np

matrix = np.arange(12).reshape(3, 4)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

# Basic slicing -- returns a VIEW
row_view = matrix[1, :]      # [4 5 6 7], shares memory with matrix
row_view[0] = 99
print(matrix[1, 0])          # 99 -- original was mutated!

# Fancy indexing -- returns a COPY
selected_rows = matrix[[0, 2]]   # rows 0 and 2, independent copy
selected_rows[0, 0] = -1
print(matrix[0, 0])              # 0 -- original untouched

# Boolean masking -- returns a COPY
mask = matrix > 6
filtered = matrix[mask]          # 1-D array of elements > 6
print(filtered)                  # [ 7  8  9 10 11]

A useful mnemonic: slices with colons (:) are views (cheap, memory-sharing); indexing with lists, arrays, or booleans is fancy indexing (expensive-ish, always a fresh copy).

arr[mask][0] = value does NOT modify arr, because arr[mask] already produced a copy before the assignment ran. Use arr[mask, 0] = value or arr[np.where(mask)] patterns, or restructure with arr[idx] = value on a single indexing step, to actually mutate in place.

  • Basic slicing (start:stop:step) returns a view sharing memory with the original array.
  • Fancy indexing (list/array of indices) always returns a new, independent copy.
  • Boolean masking (arr[condition]) also always returns a copy, never a view.
  • Mutating a view mutates the original array; mutating a copy does not.
  • Chained indexing like arr[mask][0] = x fails silently because the first step already copied.
  • Use .copy() explicitly whenever you need an independent array from a slice.

Practice what you learned

Was this page helpful?

Topics covered

#Python#PandasNumPyStudyNotes#DataScience#ArrayIndexingAndSlicing#Array#Indexing#Slicing#Returns#DataStructures#SQL#StudyNotes#SkillVeris