Lists
Lists are ordered, mutable sequences that can hold any mix of types. They're one of Python's most versatile data structures โ you'll use them in almost every program.
# Creating lists
empty = []
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True, None]
nested = [[1, 2], [3, 4], [5, 6]]
# From other iterables
from_range = list(range(10)) # [0, 1, 2, ..., 9]
from_string = list("hello") # ['h', 'e', 'l', 'l', 'o']
from_tuple = list((1, 2, 3)) # [1, 2, 3]Accessing Elements
fruits = ["apple", "banana", "cherry", "date"]
fruits[0] # "apple" (first)
fruits[-1] # "date" (last)
fruits[1:3] # ["banana", "cherry"] (slice)
fruits[:2] # ["apple", "banana"]
fruits[2:] # ["cherry", "date"]
fruits[::-1] # reversed listModifying Lists
fruits = ["apple", "banana", "cherry"]
# Adding
fruits.append("date") # Add to end: ["apple","banana","cherry","date"]
fruits.insert(1, "avocado") # Insert at index: ["apple","avocado","banana","cherry","date"]
fruits.extend(["fig", "grape"]) # Add multiple from iterable
fruits += ["kiwi"] # Same as extend
# Removing
fruits.remove("banana") # Remove first occurrence by VALUE (ValueError if missing)
popped = fruits.pop() # Remove+return LAST element
popped = fruits.pop(0) # Remove+return element at INDEX 0
del fruits[1] # Delete at index (no return)
del fruits[1:3] # Delete a slice
fruits.clear() # Remove all
# Modifying
fruits[0] = "APPLE" # Replace by index
fruits[1:3] = ["X", "Y"] # Replace a sliceSearching and Sorting
nums = [3, 1, 4, 1, 5, 9, 2, 6]
# Searching
nums.index(4) # 2 โ index of first occurrence (ValueError if not found)
nums.count(1) # 2 โ how many times 1 appears
4 in nums # True โ membership test (O(n))
min(nums) # 1
max(nums) # 9
sum(nums) # 31
len(nums) # 8
# Sorting
nums.sort() # In-place, ascending [1,1,2,3,4,5,6,9]
nums.sort(reverse=True) # In-place, descending
sorted_copy = sorted(nums) # Returns NEW sorted list (original unchanged)
nums.reverse() # Reverse in-place
# Sorting with key function
words = ["banana", "Apple", "cherry"]
words.sort(key=str.lower) # Case-insensitive sortCopy vs Reference
# DANGER: list assignment is a reference, not a copy!
original = [1, 2, 3]
alias = original # Both point to SAME list
alias.append(4)
print(original) # [1, 2, 3, 4] โ modified!
# Shallow copy
copy1 = original.copy()
copy2 = list(original)
copy3 = original[:] # Slice copy
# Deep copy (for nested lists)
import copy
nested = [[1, 2], [3, 4]]
deep = copy.deepcopy(nested)
deep[0].append(99)
print(nested) # [[1, 2], [3, 4]] โ unchangedLists as Stacks and Queues
# Stack (LIFO) โ use append/pop (both O(1))
stack = []
stack.append(1)
stack.append(2)
stack.append(3)
stack.pop() # 3
# Queue (FIFO) โ use collections.deque (O(1) for both ends)
from collections import deque
queue = deque()
queue.append("first")
queue.append("second")
queue.append("third")
queue.popleft() # "first"
# Don't use list.pop(0) for queues โ it's O(n)!Key Takeaways
- append() adds one, extend() adds many
- pop() returns the removed element โ use for stacks
- sort() modifies in-place, sorted() returns new list
- a = b is an alias, not a copy โ use .copy() or list()
- Use deque for queues โ list.pop(0) is O(n)
Practice Exercises
- Write a function that removes duplicates from a list while preserving order (no set โ maintain sequence).
- Implement a stack-based function to check if brackets are balanced:
"({[]})"โ True,"({)}"โ False. - Given a list of integers, return a new list where each element is the running total (cumulative sum).
- Write a function that rotates a list
npositions to the right. Do it with slicing in one line.