Indexing and Slicing Arrays
Overview
Slices look like list slices and behave differently in one important way.
What You Will Learn in This Lesson
By the end of this lesson, you will be able to:
- Index and slice a one-dimensional array the way you already index a list.
- Explain what a view is, and why writing into one changes the original.
- Use
.copy()when you need the array left alone. - Index a two-dimensional array with one pair of brackets.
Why This Matters
Array slicing looks identical to list slicing and behaves differently in exactly one respect — it does not copy. That single difference is behind a whole class of bug where a function quietly edits its caller's data. It is worth meeting deliberately, once, rather than discovering it in an analysis you have already published.
Step 1: Indexing reads the same as a list
Positions from zero, negatives from the end, and a slice for a run of them. Everything you know from lists transfers.
Positions and ranges
A single index gives one element. A slice gives a run, with the stop exclusive, exactly as in a list.
import numpy as np
a = np.array([10, 20, 30, 40, 50])
print(a[0])
print(a[-1])
print(a[1:4])
print(a[:2])
print(a[::2])
Two dimensions, one pair of brackets
For a 2-D array you can write a[1][2] as you would with nested lists, but a[1, 2] is the numpy way and it is what lets you slice both directions at once.
import numpy as np
table = np.array([[1, 2, 3], [4, 5, 6]])
print(table[1, 2]) # row 1, column 2
print(table[0]) # a whole row
print(table[:, 1]) # a whole column
table[:, 1] reads as "every row, column 1". Pulling a column out of a list of lists took a comprehension; here it is a slice.
Mini Practice #1: Take a column
Try It YourselfFrom the table below, print the second column, then the last row, then the single value in the bottom right — each in one expression.
Step 2: A slice is a view, not a copy
This is the difference that catches people. Slicing a list gives you a new list; slicing an array gives you a window onto the same memory.
Writing through the window
Assigning into a slice changes the array it came from. Nothing warns you, because as far as numpy is concerned you asked for a view and then wrote into it.
import numpy as np
a = np.array([1, 2, 3, 4])
part = a[1:3]
part[0] = 99
print(part)
print(a) # the 99 is in here too
The same code with a list does not do this
Worth running side by side once, so the difference is a thing you have seen rather than a thing you were told.
values = [1, 2, 3, 4]
part = values[1:3]
part[0] = 99
print(part)
print(values) # untouched
Ask for a copy when you want one
If a function is going to modify what it was handed, take a copy first — or return something new instead of editing in place. The cost of the copy is almost always smaller than the cost of the bug.
import numpy as np
a = np.array([1, 2, 3, 4])
part = a[1:3].copy()
part[0] = 99
print(part)
print(a) # safe
Mini Practice #2: Prove it to yourself
Try It YourselfRun this as it stands and note what a prints. Then add .copy() to the slice and run it again.
Step 3: When to Use It
Reading part of an array
A slice is a cheap view: ideal for looking at, summarising or passing along a range of values.
first_week = daily[:7]
Changing part of an array on purpose
Assigning into a slice updates the original — useful when that is exactly what you mean.
When Not to Use It
Do not modify a slice you meant to be a separate copy. Call .copy() first, or a change to the “copy” quietly rewrites the original data.
End-of-Lesson Exercises
Exercise 1: Everything but the ends
Write middle(values) that returns a list of everything except the first and last item.
A slice from 1 to -1 drops one from each end, and slices clamp rather than raise when there is nothing left to take.
Exercise 2: Zero a range without touching the original
Write blanked(values, start, stop) that returns a new array with the elements from start up to (not including) stop set to 0. The array you were given must come back unchanged.
Take a .copy() first, then assign 0 into the slice of the copy. Assigning into a slice of the original would change the caller's array, which is the thing this exercise is checking.