Learning LibraryCore Coding LibraryTeens

List Indexing in Python: positions, and counting from the end

A list is only useful if you can reach into it. Indexing pulls out one element — wave[0] is the front enemy, and wave[-1] is the one at the very back.

The big idea

list[i] returns the element at position i (starting at 0); a negative i counts backward from the end.

See it in code

1The basics

list[i] returns the element at position i, counting from 0. Here are six enemy x-positions: wave[0] is the first, wave[2] the third:

python
wave = [55, 129, 203, 277, 351, 425]
print("First:", wave[0])
print("Third:", wave[2])
Run it — position 0, then position 2:
First: 55
Third: 203

wave[0] is 55; wave[2] skips to the third value. Zero-based means index 2 is the third slot, not the second.

2A step further

A negative index counts backward from the end — no need to know the length. wave[-1] is the last enemy, wave[-2] the one before it:

python
wave = [55, 129, 203, 277, 351, 425]
print("Last:", wave[-1])
print("Second to last:", wave[-2])
Run it — the back of the line, reached from the end:
Last: 425
Second to last: 351

-1 grabbed 425 without you writing wave[len(wave) - 1]. Now let's reach into a wave of real objects the same way.

3In our world

Same six-enemy wave, now as Enemy objects. wave[0] is the first created (its x is 55), and wave[-1] is the back of the line — so we can draw just the ends:

python
from game import Stage, Enemy

screen = Stage.create()
Stage.clear(screen)

wave = [Enemy(55 + i * 74, 90) for i in range(6)]

print("Front enemy x:", wave[0].x)
print("Back enemy x:", wave[-1].x)

wave[0].draw(screen)
wave[-1].draw(screen)
Run it — only the front and back enemies are drawn:
Front enemy x: 55
Back enemy x: 425
Two purple enemy sprites near the top of a dark play area — one on the far left, one on the far right.

wave[0] reached the first enemy, wave[-1] the last — and 425 is exactly the 55 and 425 from the warm-up. Negative indexing saves you from writing wave[len(wave) - 1] just to get the final item.

The same idea, everywhere

Indexing is universal to ordered data: prices[-1] is today's close, dna[0] is the first base, row[2] is the third column. Slicing extends it — wave[:3] is the first three, wave[-2:] the last two — for grabbing a whole span at once.

Try it yourself

Print wave[2].x and predict it first. Then take a slice: for e in wave[1:4]: e.draw(screen) draws the middle three enemies. Notice a slice gives back a list, while a single index gives back one item.

The common mistake

The off-by-one error. A list of length 6 has valid indexes 0 through 5; wave[6] raises IndexError because there's no seventh slot. The last item is always at index len(list) - 1, or simply -1.

What it unlocks

Indexing and slicing extend lists and list methods, and underpin the sequence analysis you'll do on DNA strings.

Want the simpler version? Read the Kids version →