← Home

029. String Slicing

Extract sub-sequences with start:stop:step

029. String Slicing

RAM Manager — Parsing Log Lines

Aryan’s RAM manager writes events to a structured log file. Each line has a fixed format:

2024-03-15 ERROR: disk full
0123456789
  • Characters 0–9 (10 chars): the date "2024-03-15"
  • Characters 11–15 (5 chars): the level "ERROR"
  • Characters 18 onwards: the message "disk full"

His get_date() uses log[0:9] — that is 9 characters (indices 0–8), cutting off the last digit of the date. He gets "2024-03-1" instead of "2024-03-15".

Also, get_message() starts at index 17 instead of 18, so it includes the leading space from ": ", returning " disk full" instead of "disk full".

The lesson: s[start:stop] includes start but excludes stop. To get 10 characters starting at 0, use s[0:10] — not s[0:9].


💡 Fun fact: Python’s exclusive-stop slicing convention (s[0:10] gives 10 items, not 11) was chosen by Guido van Rossum because it makes several properties elegant: len(s[a:b]) == b - a, slices can be concatenated as s[:n] + s[n:] == s, and an empty slice s[n:n] is always valid. Edsger Dijkstra wrote a famous argument for this convention in 1982.

⚠️ Watch out: The most common slicing mistake is using s[0:9] when you want the first 10 characters, forgetting that stop is exclusive. To get n characters starting at index i, the stop must be i + n, not i + n - 1.

🤔 Think about it: s[::-1] reverses a string in one expression, but s[1::-1] only reverses the first two characters. The step -1 means “go backwards” — so what does the start and stop represent when stepping backwards, and why does omitting them ([::-1]) give you the full reversed string?

Learning objectives

  • Extract substrings with s[start:stop]
  • Use negative indices in slices
  • Reverse strings with s[::-1]

Key concepts

  • string slicing
  • start stop step
  • substring

Try it

Concept detail

Slicing syntax: s[start:stop:step]. Stop is EXCLUSIVE (not included). Defaults: start=0, stop=len(s), step=1. Omit any: s[:5] == s[0:5], s[2:] == s[2:len(s)]. Step: s[::2] every other char, s[::-1] reversed. Slicing never raises IndexError — out-of-range just gives fewer characters. s[1:100] on a 5-char string gives s[1:5] without error. Slicing creates a new string (strings are immutable).

Solution

def get_date(log):
    return log[0:10]

def get_level(log):
    return log[11:16]

def get_message(log):
    return log[18:]

def reverse_string(s):
    return s[::-1]

Tests

LOG = "2024-03-15 ERROR: disk full"

def test_get_date():
    assert get_date(LOG) == "2024-03-15"

def test_get_level():
    assert get_level(LOG) == "ERROR"

def test_get_message():
    assert get_message(LOG) == "disk full"

def test_reverse_hello():
    assert reverse_string("hello") == "olleh"

def test_reverse_empty():
    assert reverse_string("") == ""

Resources