← Home

028. String Indexing

Zero-based indexing with negative wraparound

028. String Indexing

RAM Manager — Parsing Process Serial Numbers

Aryan’s RAM manager reads equipment serial numbers from a hardware inventory file. Each serial follows the format "XXXX-YYYYMMDD-N":

LAPT-20240315-7   → product code: LAPT, last digit: 7
SRVR-20231201-3   → product code: SRVR, last digit: 3

He writes functions to extract the product code (first 4 chars), the last character (sequence number), and the first character (product family initial). His attempt has three off-by-one mistakes: serial[1:4] misses the first char, serial[1] returns the second char instead of the first, and serial[len(serial) - 2] returns the second-to-last character instead of the last.

The lesson: Python indexing is zero-based. The first element is s[0], not s[1]. s[len(s)-1] works but s[-1] is cleaner and less error-prone — negative indices count from the end and are always correct regardless of string length.


💡 Fun fact: Zero-based indexing dates back to the design of the C language in the early 1970s, where array indices represented pointer offsets from the start address. Python inherited zero-based indexing from C, but added negative indices as a purely Pythonic convenience — no equivalent exists in C arrays.

⚠️ Watch out: Off-by-one errors in indexing are the most common string bug — s[1:4] returns 3 characters (indices 1, 2, 3), not 4. When in doubt, count the characters by hand with the actual string and verify your slice boundaries before trusting the result.

🤔 Think about it: s[-1] is equivalent to s[len(s) - 1]. Both work, but -1 is shorter and will never accidentally go out of range. Can you think of a situation where s[len(s) - 1] would behave differently from s[-1] — or are they always identical for any non-empty string?

Learning objectives

  • Access individual characters with positive indices (0-based)
  • Use negative indices to count from the end
  • Avoid off-by-one errors with string indexing

Key concepts

  • string indexing
  • zero-based indexing
  • negative indices

Try it

Concept detail

Python strings are sequences indexed from 0. s[0] is first, s[1] is second, s[-1] is last. Valid positive indices: 0 to len(s)-1. Valid negative indices: -1 to -len(s). Going out of range raises IndexError: s[len(s)] is always wrong. Indices can be computed: s[len(s)//2] gets the middle character. Strings are immutable — you can read s[0] but not assign s[0] = ‘x’.

Solution

def get_product_code(serial):
    return serial[0:4]

def get_last_char(serial):
    return serial[-1]

def get_first_char(serial):
    return serial[0]

Tests

SERIAL = "LAPT-20240315-7"

def test_product_code():
    assert get_product_code(SERIAL) == "LAPT"

def test_last_char():
    assert get_last_char(SERIAL) == "7"

def test_first_char():
    assert get_first_char(SERIAL) == "L"

def test_last_char_negative_index():
    assert get_last_char("ABCDE") == "E"

Resources