Slicing
Overview
A list is an ordered, mutable sequence of any Python objects. You create one with square brackets and access elements by zero-based index — negative indexes count from the end: items = ['a', 'b', 'c', 'd'] items[0] # 'a' — first items[-1] # 'd' — last Slicing returns a new list — it does NOT modify the original: items[1:3] # ['b', 'c'] — index 1 up to (not including) 3 items[::-1] # ['d', 'c', 'b', 'a'] — reversed copy Key methods (all mutate in place, return None unless noted): append(x) — add x to the end extend([x, y]) — add all items from an iterable pop(i) — remove and RETURN item at index i (default: last) insert(i, x) — insert x before index i remove(x) — remove the first occurrence of x (ValueError if absent) sort() — sort in place; sorted(lst) returns a new sorted list index(x) — return the first index of x (ValueError if absent) Think of a list as a numbered row of slots — you can insert, delete, and reorder freely because slots shift to close the gap.
Lists are the default container for ordered data in Python: API response arrays, database result sets, pipeline stages, log entries. Knowing slicing and the right method prevents off-by-one bugs and unexpected None returns.
Where used: FastAPI response arrays of records, SQLModel query result lists, Collecting pipeline stage outputs
Why learn this
- Slicing API result lists (page = results[offset:offset+limit]) for pagination in FastAPI endpoints
- Using pop() and append() correctly — both return None by accident is one of the most common beginner bugs
Code walkthrough
log = ['INFO', 'DEBUG', 'ERROR', 'INFO', 'WARN']
print(log[0])
print(log[-1])
print(log[1:3])
log.append('ERROR')
log.sort()
print(log)
Focus: log[1:3] returns a new list without changing log; append and sort mutate log in place — the final print shows both effects accumulated.
Common mistakes
- Assigning the return value of append or sort: result = items.append(x) sets result to None because append mutates in place and returns None. These mutating methods return nothing useful — call them as statements.
- Slicing thinking it modifies the original: items[1:3] returns a NEW list — the original is unchanged. To replace a slice in place, assign to the slice: items[1:3] = ['x', 'y'].
- Using remove() without checking membership first: items.remove(x) raises ValueError if x is not in the list. Guard with if x in items: or catch ValueError.
Glossary
- mutable
- An object whose internal state or data can be changed after it is created, e.g. `items = [1, 2]; items.append(3)` modifies the same list.
- pagination
- The process of dividing a large set of results into smaller, more manageable pages, typically used in web APIs, e.g. `results[0:10]` for page 1, `results[10:20]` for page 2.
Recall questions
- What does a negative index like -1 mean on a list?
- Does slicing a list modify the original list?
- What does list.pop(i) return?
- What does list.append() return?
Understanding checks
What does this code print?
['b', 'c']
Slicing a list (`items[1:]`) creates a *new* list. Modifying the original `items` list by appending 'd' does not affect the `subset` list.
Why does this code print `None` instead of `['hello', 'world']`?
Because `sort()` mutates the list in place and returns `None`.
List methods like `sort()` and `append()` change the original list rather than returning a new one. To fix it, call `words.sort()` as a statement, then print `words`.
Practice tasks
Fix the pagination logic
The `paginate` function currently returns all items starting from `page * page_size`, but it doesn't limit the returned list to `page_size` elements. Modify the slice so it correctly returns a list of exactly `page_size` elements for the given page.
Challenge
Request queue manager
Write enqueue(queue, item) and dequeue(queue) functions that treat a list as a FIFO queue. enqueue appends to the end; dequeue removes and returns from the front, returning None when the queue is empty (do not raise). Print three enqueue calls, then dequeue until empty.
Continue learning
Previous: Mutable vs immutable types
Next: Comprehensions
Next: Shallow vs deep copy
Next: list vs tuple