Lists
In Python, a List is an ordered, mutable collection of items. It is arguably the most fundamental and versatile data structure in the language. If you need to store a sequence of objects that might change over time, the list is your primary tool.
1. What is a List?
Section titled “1. What is a List?”A list is a container that can hold any number of items, and those items can be of any data type (integers, strings, even other lists).
- Ordered: The items have a defined order that will not change unless you explicitly change it.
- Mutable: You can add, remove, or change items after the list has been created.
- Dynamic: Lists can grow and shrink in size as needed.
# An empty listempty_list = []
# A list of integersprime_numbers = [2, 3, 5, 7, 11]
# A list with mixed types (though usually avoided for clarity)mixed_list = [1, "Hello", 3.14, True]
# A nested list (list of lists)matrix = [[1, 2], [3, 4]]2. Accessing Items: Indexing and Slicing
Section titled “2. Accessing Items: Indexing and Slicing”Since lists are ordered, every item has a specific position, known as its index.
Indexing
Section titled “Indexing”Python uses zero-based indexing, meaning the first item is at index 0.
fruits = ["apple", "banana", "cherry", "date"]
print(fruits[0]) # Output: appleprint(fruits[2]) # Output: cherry
# Negative indexing starts from the endprint(fruits[-1]) # Output: date (last item)print(fruits[-2]) # Output: cherry (second to last)Slicing
Section titled “Slicing”Slicing allows you to extract a sub-portion of a list. The syntax is list[start:stop:step].
start: The index where the slice begins (inclusive).stop: The index where the slice ends (exclusive).step: The interval between items (optional, defaults to 1).
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(numbers[2:5]) # [2, 3, 4]print(numbers[:3]) # [0, 1, 2] (from start to index 3)print(numbers[7:]) # [7, 8, 9] (from index 7 to end)print(numbers[::2]) # [0, 2, 4, 6, 8] (every second item)print(numbers[::-1]) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] (reversed)3. Modifying Lists (Mutability)
Section titled “3. Modifying Lists (Mutability)”Unlike strings, lists are mutable. You can change an item by assigning a new value to its index.
colors = ["red", "green", "blue"]colors[1] = "yellow"print(colors) # ['red', 'yellow', 'blue']Common List Methods
Section titled “Common List Methods”Python provides several built-in methods to manipulate lists:
| Method | Description | Example |
|---|---|---|
append(x) | Adds an item x to the end. | L.append(4) |
extend(iterable) | Appends all items from an iterable. | L.extend([5, 6]) |
insert(i, x) | Inserts item x at index i. | L.insert(0, "first") |
remove(x) | Removes the first occurrence of x. | L.remove("apple") |
pop([i]) | Removes and returns item at index i (default last). | item = L.pop() |
clear() | Removes all items from the list. | L.clear() |
index(x) | Returns the index of the first occurrence of x. | i = L.index("banana") |
count(x) | Returns the number of times x appears. | num = L.count(1) |
sort() | Sorts the list in place. | L.sort() |
reverse() | Reverses the list in place. | L.reverse() |
4. Context: Why and When to Use Lists
Section titled “4. Context: Why and When to Use Lists”Lists should be your “go-to” structure whenever you have a collection of similar items that you need to maintain in a specific order.
Use a List when:
- You need a sequence of items.
- You need to modify the collection (add/remove items).
- The order of items is important (e.g., a “To-Do” list or a list of user IDs).
Avoid a List when:
- You need to store unique items only (use a Set).
- You need to look up items by a specific label or key (use a Dictionary).
- You have a massive amount of numerical data and need high-performance mathematical operations (use NumPy arrays).
5. Detailed Example: A Task Manager
Section titled “5. Detailed Example: A Task Manager”Let’s build a simple logic for a task manager that utilizes various list operations.
tasks = ["Email Client", "Buy Milk", "Fix Bug"]
# 1. Add a new task to the endtasks.append("Go to Gym")
# 2. Add an urgent task to the beginningtasks.insert(0, "URGENT: Server Down")
# 3. Mark a task as done (remove it)tasks.remove("Buy Milk")
# 4. Remove the last task addedfinished_task = tasks.pop()
# 5. Sort the remaining tasks alphabeticallytasks.sort()
print(f"Tasks remaining: {tasks}")print(f"Just finished: {finished_task}")Output:
Tasks remaining: ['Email Client', 'Fix Bug', 'URGENT: Server Down']Just finished: Go to Gym6. Under the Hood: Dynamic Arrays
Section titled “6. Under the Hood: Dynamic Arrays”How does Python manage lists in memory? Python lists are implemented as Dynamic Arrays.
Memory Allocation
Section titled “Memory Allocation”When you create a list, Python allocates a block of memory to hold a certain number of references to objects.
- Contiguous Memory: The references (pointers) are stored next to each other in memory. This is why indexing (
L[5]) is extremely fast—the computer just calculates the memory offset. - Over-allocation: To make
append()efficient, Python doesn’t just allocate space for the items you have. It allocates extra space. - Resizing: When the list is full and you try to
append()another item, Python:- Allocates a new, larger block of memory.
- Copies the existing references to the new block.
- Deletes the old block.
- Adds the new item.
Performance (Big O Notation)
Section titled “Performance (Big O Notation)”- Access by Index: $O(1)$ (Constant time)
- Append: $O(1)$ (Amortized constant time)
- Insert/Delete at the end: $O(1)$
- Insert/Delete in the middle: $O(n)$ (Because all subsequent items must be shifted)
- Search for an item: $O(n)$ (Because it might have to check every item)