JJoeven

Curriculum/Python

Index and Slice

Count from 0. A slice is a piece of a list or a string. Off-by-one errors break chunks of text and log windows.

beginner18 min9 / 37

An index is a position number. Python starts at 0. The first item is index 0. The second is index 1. The last item of a 4-item list is index 3, which is also -1.

Index 0 is the first box
abcd

A slice [1:3] keeps b and c. The stop index is not included. The same rule works on text.

Index 0 is the first box

A slice is a piece. You write it as [start:stop]. You get items from start up to — but not includingstop. The same rules work on a string (text) and on a list. Learn them once. Use them on prompts, logs, and chunks.

Count from zero

word[0] is the first character. word[-1] is the last. Negative indexes count from the end: -2 is the second last. word[-len(word)] is the first character again.

A missing index crashes. Python stops with IndexError: that position does not exist. A slice does not crash. A slice that is past the end is just empty. That difference matters when you take memory[-1] on an empty log (crash) versus memory[-5:] on a short log (fine).

python
word = class="tok-s">"hello"
print(word[0])    class="tok-c"># h
print(word[-1])   class="tok-c"># o
print(word[1:4])  class="tok-c"># ell  (indexes 1, 2, 3 — not 4)

nums = [class="tok-s">"a", class="tok-s">"b", class="tok-s">"c", class="tok-s">"d"]
print(nums[1:4])  class="tok-c"># ['b', 'c', 'd']
print(nums[9:12]) class="tok-c"># []

If you need the last item but the list might be empty, check first:

python
if nums:
    print(nums[-1])
else:
    print(class="tok-s">"no items")

Start, stop, and step

You can skip the start or the stop. You can also add a step (how many items to jump).

CodeMeaning
s[0]Item at index 0
s[-1]Last item
s[1:4]Indexes 1, 2, 3 (stop is not included)
s[:3]From the start up to index 3
s[3:]From index 3 to the end
s[::2]Every second item
s[:]A copy (a new list with the same items)
s[-5:]Last five items (or all, if fewer)

s[start:stop:step] is the full form. s[::-1] walks backward. That is a trick. Real agent code uses slices to keep a tail of a log, not to reverse a prompt. If you reverse a transcript, the model sees the story backwards.

A step of 2 on "abcde" with [0:5:2] is "ace". Useful in puzzles. Rare in agents. Prefer a loop if you are picking items by a rule other than “a window of the log.”

Copy with [:]

b = a does not copy. Both names point at the same list. If you append through b, you also change a.

c = a[:] makes a new list. Changing c does not change a. list(a) is the same kind of copy. Both are shallow: inner lists inside a are still shared. Deep copy comes later. For a list of strings, [:] is enough.

python
original = [1, 2, 3]
same = original
copy = original[:]
same.append(99)
print(original)  class="tok-c"># [1, 2, 3, 99]
print(copy)      class="tok-c"># [1, 2, 3]

Strings do not need this copy for safety, because you cannot change a string in place. t = s for two strings is still two names on one text, but nothing can edit that text.

Off-by-one breaks chunking

Chunking means cutting a long text into small pieces (chunks) so a model can read them. Each chunk is a slice. The next chunk should start where the last one stopped.

Off-by-one means you are one item too short or too long. It happens because stop is not included.

If you want 4 letters, the stop is start + 4, not start + 3. The next chunk should start at that same stop. If you start the next chunk one too far, you skip a letter. If you stop one too soon, you drop a letter.

python
text = class="tok-s">"abcdefgh"
print(text[0:4], text[4:8])  class="tok-c"># abcd efgh  — good 4-letter chunks
print(text[0:3], text[3:6])  class="tok-c"># abc def    — too short (off by one)

A small loop that does this right:

python
text = class="tok-s">"abcdefgh"
size = 4
start = 0
while start < len(text):
    piece = text[start:start + size]
    print(piece)
    start = start + size

The next start is the old stop. That single assignment is the whole trick.

A log window is the same arithmetic. memory[-8:] means start at len(memory)-8, stop at the end. If you write memory[-8:-1] you drop the last item. That is a classic off-by-one: you wanted the last eight, including the newest. The missing last row is often the observation the model needed. Prefer [-n:] with no stop, or [start:].

Indexes on a 5-item list are 0,1,2,3,4. There is no 5. nums[5] crashes. nums[5:] is empty. When you compute i + size as the next start, that number is allowed to equal len. The next slice is then empty and your while loop should stop. start < len(text) is the right test. start <= len(text) would spin on empty slices.

Common mistakes

  • memory[-1] on an empty list.
  • Using s[0:4] and thinking index 4 was included.
  • b = a when you needed a copy.
  • Overlapping chunks by restarting at stop - 1 without meaning to.
  • Reversing a log with [::-1] and sending that to the model.
Live PythonOpen full playgroundpython
Output
Run to execute this in your browser. Nothing is sent to a server.

Change the chunk size in your head from 4 to 2 and predict text[0:2], text[2:4], text[4:6], text[6:8]. Then print those slices. Prediction is how off-by-one dies.

How agents use this

Agents slice the last few messages so the prompt stays short: transcript[-10:]. They also slice long documents into chunks. If the stop index is wrong, a chunk loses a letter or skips one. That is an off-by-one bug. The same slice rules work on strings and on lists.

A window that is too long wastes tokens and buries the newest observation. A window that is too short forgets the user goal. Pick a number, slice, print len(window). When cost spikes, shorten the slice before you blame the model.

Copy before you isolate: if you pass a slice of a log into a helper that appends, a slice of a list is already a new list, so appends stay in the helper. A slice of a string is a new string anyway. Indexing a single dict out of a list of dicts does not copy the dict. Nested data comes in two lessons. For now: slices of lists copy the outer row of labels.

Check your understanding

What does "abcd"[1:3] give you?