Index lookups are the foundation of accessing elements in strings, lists, tuples, and other sequences in Python — using square brackets [] with integer positions to retrieve individual items or slices. Positive indices start at 0 (first element) and go up to len(sequence) - 1 (last element); negative indices count backward from -1 (last element) to -len(sequence) (first element). Indexing returns a single element; slicing with [start:end:step] returns a new sequence (substring for strings, sublist for lists). In 2026, index lookups remain essential — used constantly in text parsing, data extraction, log analysis, pandas/Polars column operations, array manipulation, and any task requiring positional access or substring/sublist extraction. They are fast, zero-copy for slices (views in some cases), and handle out-of-bounds gracefully in slicing (no errors, just empty or partial results).
Here’s a complete, practical guide to index lookups in Python: single-element access, negative indexing, slicing patterns, real-world examples, performance notes, and modern best practices with type hints, pandas/Polars integration, and error handling.
Single-element index lookup retrieves one character (string) or item (list/tuple) — raises IndexError if out of range.
text = "Hello, world!"
mylist = [10, 20, 30, 40, 50]
print(text[0]) # 'H' (first character)
print(text[4]) # 'o'
print(text[-1]) # '!' (last character)
print(text[-3]) # 'l' (third from end)
print(mylist[0]) # 10
print(mylist[-1]) # 50
Slicing extracts a range — [start:end] includes start up to (but not including) end; omit start for beginning, end for end; step skips elements.
print(text[7:12]) # 'world' (indices 7 to 11)
print(text[:5]) # 'Hello' (first 5 characters)
print(text[7:]) # 'world!' (from index 7 to end)
print(text[::2]) # 'Hlo ol!' (every second character)
print(text[::-1]) # '!dlrow ,olleH' (reversed string)
print(mylist[1:4]) # [20, 30, 40] (indices 1 to 3)
print(mylist[::-1]) # [50, 40, 30, 20, 10] (reversed list)
Real-world pattern: parsing structured text or extracting fields — indexing/slicing pulls specific parts from logs, filenames, IDs, or pandas columns.
# Extract domain from URL
url = "https://www.example.com/path/to/page.html"
domain = url.split("//")[1].split("/")[0]
print(domain) # www.example.com
# Clean phone number: remove parentheses, spaces, dashes
phone = "(123) 456-7890"
clean = ''.join(c for c in phone if c.isdigit())
print(clean) # 1234567890
# pandas vectorized indexing/slicing
import pandas as pd
df = pd.DataFrame({'code': ['ABC-123', 'XYZ-456', 'DEF-789']})
df['prefix'] = df['code'].str[:3] # 'ABC', 'XYZ', 'DEF'
df['number'] = df['code'].str[4:] # '123', '456', '789'
print(df)
Best practices make index lookups safe, readable, and performant. Use negative indices for end-relative access — text[-1] clearer than text[len(text)-1]. Prefer slicing over indexing in loops — text[1:-1] removes first/last chars efficiently. Modern tip: use Polars for large text columns — pl.col("text").str.slice(0, 5) or .str.replace(...) is 10–100× faster than pandas .str. Add type hints — str or pd.Series[str] — improves static analysis. Handle out-of-range safely — slicing returns empty string/list instead of error; use text[start:end] over text[index] when bounds uncertain. Avoid slicing huge strings repeatedly — use views or memoryview for large text processing. Combine with split()/join() — text.split('-')[1] for delimited extraction. Use regex for complex patterns — re.search(r'\d+', text) — but slicing faster for fixed positions.
Index lookups and slicing give precise control over sequences — access elements, extract substrings/sublists, reverse, skip, or clean data efficiently. In 2026, use negative indices, vectorize with .str in pandas/Polars, add type hints, and handle bounds safely. Master indexing, and you’ll parse, extract, and transform data quickly and correctly.
Next time you need a character, item, or substring — reach for indexing and slicing. It’s Python’s cleanest way to say: “Give me exactly this part.”