The Gardener's Greenhouse โ 60+ list methods, operations, and patterns. Search, filter by category, and copy code examples instantly. Covers built-in methods, operators, comprehensions, slicing, and common patterns.
Add a single element to the end of the list. If x is a list, it becomes a nested list.
fruits = ['apple', 'banana'] fruits.append('cherry') # fruits โ ['apple', 'banana', 'cherry'] # Appending a list creates nesting: fruits.append(['date', 'elderberry']) # fruits โ ['apple', 'banana', 'cherry', ['date', 'elderberry']]
Extend the list by appending all elements from the iterable. Use this to flatten one level.
a = [1, 2, 3] a.extend([4, 5, 6]) # a โ [1, 2, 3, 4, 5, 6] # Equivalent to: a += [4, 5, 6] # Works with any iterable: strings, tuples, sets, dict keys
Insert element x at position i. Negative indices count from the end. Existing elements shift right.
nums = [10, 30, 40] nums.insert(1, 20) # Insert at index 1 # nums โ [10, 20, 30, 40] nums.insert(0, 5) # Prepend nums.insert(-1, 35) # Insert before last element # nums โ [5, 10, 20, 30, 35, 40]
Concatenate two lists, returning a new list. Original lists are unchanged.
a = [1, 2] b = [3, 4] c = a + b # c โ [1, 2, 3, 4] # a and b remain unchanged # Can chain: a + b + [5, 6]
Repeat a list n times, returning a new list. Useful for initialization and padding.
zeros = [0] * 5 # zeros โ [0, 0, 0, 0, 0] pattern = [1, 2] * 3 # pattern โ [1, 2, 1, 2, 1, 2] # โ ๏ธ Caution with mutable objects: rows = [[0] * 3] * 2 rows[0][0] = 1 # Both rows change! Use list comprehension instead.
Remove the first occurrence of value x. Raises ValueError if x is not in the list.
colors = ['red', 'green', 'blue', 'green'] colors.remove('green') # colors โ ['red', 'blue', 'green'] # Only the first 'green' is removed # Safe removal with check: if 'yellow' in colors: colors.remove('yellow')
Remove and return the item at index i (default last). Useful for stacks (LIFO).
stack = [1, 2, 3] last = stack.pop() # last = 3, stack โ [1, 2] first = stack.pop(0) # first = 1, stack โ [2] # Pop from empty list raises IndexError # Use pop() for O(1) stack operations # pop(0) is O(n) โ use collections.deque for queues
Remove all items from the list. Equivalent to del list[:] but more explicit.
data = [1, 2, 3, 4, 5] data.clear() # data โ [] # Equivalent alternatives: data[:] = [] # Same effect, keeps same object del data[:] # Same effect
Delete the item at index i, or a slice of items. No return value.
nums = [10, 20, 30, 40, 50] del nums[2] # nums โ [10, 20, 40, 50] del nums[1:3] # nums โ [10, 50] del nums[-1] # nums โ [10] # del is a statement, not a method # Cannot use: x = del nums[0] โ
Delete a slice of items from the list. More efficient than looping remove() for ranges.
nums = [0, 1, 2, 3, 4, 5, 6] del nums[2:5] # Remove indices 2,3,4 # nums โ [0, 1, 5, 6] del nums[::2] # Delete every other element # nums โ [1, 6]
Python has no built-in remove_all. Use list comprehension or a while loop.
nums = [1, 2, 1, 3, 1, 4] # Method 1: List comprehension (new list) nums = [x for x in nums if x != 1] # โ [2, 3, 4] # Method 2: While loop (in-place) while 1 in nums: nums.remove(1) # Method 3: Filter nums = list(filter(lambda x: x != 1, nums))
Return the index of the first occurrence of x. Raises ValueError if not found. Optional start/end bounds.
nums = [10, 20, 30, 20, 40] idx = nums.index(20) # idx = 1 idx2 = nums.index(20, 2) # idx2 = 3 (search from index 2) # Safe index with default: try: idx = nums.index(99) except ValueError: idx = -1 # One-liner: nums.index(99) if 99 in nums else -1
Return the number of times x appears in the list. Equality check uses ==.
nums = [1, 2, 2, 3, 2, 4] nums.count(2) # 3 nums.count(9) # 0 # Works with any type: words = ['the', 'quick', 'the'] words.count('the') # 2
Test for membership. Returns True if x is in the list, else False. Uses linear search O(n).
fruits = ['apple', 'banana', 'cherry'] 'banana' in fruits # True 'date' in fruits # False # Negation: 'grape' not in fruits # True # For frequent lookups, convert to set first: fruit_set = set(fruits) 'apple' in fruit_set # O(1) instead of O(n)
Return the smallest or largest item in the list. Optional key function for custom comparison.
nums = [3, 1, 4, 1, 5, 9] min(nums) # 1 max(nums) # 9 # With key function: words = ['cat', 'elephant', 'ant'] min(words, key=len) # 'cat' max(words, key=len) # 'elephant'
Return the sum of all items in the list. Optional start value (default 0). Works with numbers only.
nums = [1, 2, 3, 4, 5] sum(nums) # 15 sum(nums, 10) # 25 (start at 10) # Concatenate strings (unusual but valid): sum([[1], [2], [3]], []) # [1, 2, 3]
Return the number of items in the list. O(1) operation โ lists store their length internally.
items = ['a', 'b', 'c'] len(items) # 3 len([]) # 0 # Truthiness: if items: # True if len > 0 if not items: # True if len == 0
Sort the list in-place. Stable sort (Timsort). O(n log n). More memory-efficient than sorted().
nums = [3, 1, 4, 1, 5] nums.sort() # nums โ [1, 1, 3, 4, 5] nums.sort(reverse=True) # nums โ [5, 4, 3, 1, 1] # Custom key: words = ['banana', 'pie', 'Washington'] words.sort(key=len) # By length words.sort(key=str.lower) # Case-insensitive words.sort(key=lambda x: x[-1]) # By last character
Return a new sorted list from the iterable. Original is unchanged. Works with any iterable.
nums = [3, 1, 4, 1, 5] new_nums = sorted(nums) # new_nums โ [1, 1, 3, 4, 5] # nums unchanged โ [3, 1, 4, 1, 5] # Sort by multiple keys: people = [('Alice', 30), ('Bob', 25)] sorted(people, key=lambda x: x[1]) # Sort dictionary by value: d = {'a': 3, 'b': 1} sorted(d.items(), key=lambda x: x[1])
Reverse the list in-place. O(n). No return value. For a new reversed list, use slicing [::-1].
nums = [1, 2, 3, 4, 5] nums.reverse() # nums โ [5, 4, 3, 2, 1] # New reversed list (original unchanged): nums = [1, 2, 3] rev = nums[::-1] # rev โ [3, 2, 1] # nums โ [1, 2, 3]
Return a reverse iterator. Memory-efficient for large lists. Convert to list if needed.
nums = [1, 2, 3, 4] for x in reversed(nums): print(x) # 4, 3, 2, 1 # Convert to list: list(reversed(nums)) # [4, 3, 2, 1] # Memory efficient โ doesn't copy the list
Return a shallow copy of the list. Equivalent to list[:]. New list, same object references.
a = [1, 2, [3, 4]] b = a.copy() # b โ [1, 2, [3, 4]] b[0] = 99 # a[0] still 1 (independent) b[2].append(5) # a[2] also [3, 4, 5] (shared ref!) # Shallow copy alternatives: b = a[:] # Slicing b = list(a) # Constructor
Full slice creates a shallow copy. Fast and Pythonic. The idiom every Pythonista knows.
a = [1, 2, 3] b = a[:] # a[:] means "all elements" โ start to end # It's the most common copy idiom in Python # Also useful for copying other sequences: s = "hello" t = s[:] # 'hello' (strings are immutable anyway)
Create a deep copy โ recursively copies all nested objects. No shared references.
import copy a = [1, [2, 3], {'x': 4}] b = copy.deepcopy(a) b[1].append(99) # b[1] โ [2, 3, 99] # a[1] โ [2, 3] (unaffected!) # Use when you have nested mutable objects # Slower than shallow copy, but fully independent
Create a new list from any iterable. Also useful for copying lists and converting types.
a = [1, 2, 3] b = list(a) # Shallow copy # Convert other iterables: list((1, 2, 3)) # [1, 2, 3] from tuple list('abc') # ['a', 'b', 'c'] list({'x', 'y'}) # ['x', 'y'] from set list(range(5)) # [0, 1, 2, 3, 4]
Basic list comprehension. The Pythonic way to transform and filter iterables. Faster than map/filter.
# Squares of 0-9 [x**2 for x in range(10)] # โ [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] # Uppercase words words = ['hello', 'world'] [w.upper() for w in words] # โ ['HELLO', 'WORLD'] # Nested loops (flat result) [(x, y) for x in [1, 2] for y in ['a', 'b']] # โ [(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
Filtered list comprehension. Only include elements where the condition is True.
# Even numbers only [x for x in range(10) if x % 2 == 0] # โ [0, 2, 4, 6, 8] # Filter strings by length words = ['cat', 'elephant', 'dog', 'hippopotamus'] [w for w in words if len(w) > 3] # โ ['elephant', 'hippopotamus'] # Multiple conditions [x for x in range(100) if x % 3 == 0 if x % 5 == 0] # โ [0, 15, 30, 45, 60, 75, 90]
Conditional expression inside comprehension. Transform all elements, choosing values conditionally.
# FizzBuzz in one line [ 'FizzBuzz' if x % 15 == 0 else 'Fizz' if x % 3 == 0 else 'Buzz' if x % 5 == 0 else x for x in range(1, 21) ] # Replace negatives with 0 nums = [-1, 2, -3, 4] [x if x > 0 else 0 for x in nums] # โ [0, 2, 0, 4]
Generate (index, value) pairs. Essential when you need both position and value in a loop.
fruits = ['apple', 'banana', 'cherry'] list(enumerate(fruits)) # โ [(0, 'apple'), (1, 'banana'), (2, 'cherry')] list(enumerate(fruits, start=1)) # โ [(1, 'apple'), (2, 'banana'), (3, 'cherry')] # Common pattern: for i, fruit in enumerate(fruits): print(f"{i}: {fruit}")
Pair elements from multiple iterables. Stops at shortest. Use zip_longest for unequal lengths.
names = ['Alice', 'Bob', 'Carol'] ages = [30, 25, 35] list(zip(names, ages)) # โ [('Alice', 30), ('Bob', 25), ('Carol', 35)] # Transpose a matrix (unzip) matrix = [[1, 2, 3], [4, 5, 6]] list(zip(*matrix)) # โ [(1, 4), (2, 5), (3, 6)] # zip_longest for unequal lengths: from itertools import zip_longest
Apply a function to every item. Returns a map object โ convert to list. Often replaced by comprehensions.
nums = [1, 2, 3, 4] list(map(str, nums)) # โ ['1', '2', '3', '4'] list(map(lambda x: x * 2, nums)) # โ [2, 4, 6, 8] # With multiple iterables: list(map(min, [1, 2], [3, 0])) # โ [1, 0]
Keep only items where function returns True. Returns a filter object โ convert to list.
nums = [1, 2, 3, 4, 5, 6] list(filter(lambda x: x % 2 == 0, nums)) # โ [2, 4, 6] # Remove None/falsy values: data = [1, 0, 'hello', '', None, 3] list(filter(None, data)) # โ [1, 'hello', 3] # Usually prefer: [x for x in nums if x % 2 == 0]
Slice notation for extracting sublists. Negative step reverses. Omitting values uses defaults.
nums = [0, 1, 2, 3, 4, 5] nums[1:4] # [1, 2, 3] nums[:3] # [0, 1, 2] (first 3) nums[3:] # [3, 4, 5] (from index 3) nums[::2] # [0, 2, 4] (every other) nums[::-1] # [5, 4, 3, 2, 1, 0] (reversed) nums[-3:] # [3, 4, 5] (last 3)
Return True if all/any elements are truthy. Short-circuit evaluation stops at first False/True.
nums = [1, 2, 3, 4] all(x > 0 for x in nums) # True any(x > 3 for x in nums) # True # Empty list edge cases: all([]) # True (vacuously true) any([]) # False # Check if list contains any string: any(isinstance(x, str) for x in data)
Generate a sequence of numbers. Convert to list to materialize. Memory-efficient for loops.
list(range(5)) # [0, 1, 2, 3, 4] list(range(1, 6)) # [1, 2, 3, 4, 5] list(range(0, 10, 2)) # [0, 2, 4, 6, 8] list(range(5, 0, -1)) # [5, 4, 3, 2, 1] # Create index list: list(range(len(my_list)))
Multiple techniques to flatten one or more levels of nested lists.
nested = [[1, 2], [3, 4], [5, 6]] # Flatten one level (comprehension): [x for sub in nested for x in sub] # โ [1, 2, 3, 4, 5, 6] # Using itertools: from itertools import chain list(chain.from_iterable(nested)) # Deep flatten (arbitrary nesting): def flatten(lst): for x in lst: if isinstance(x, list): yield from flatten(x) else: yield x
Split a list into fixed-size chunks. Useful for pagination and batch processing.
data = [1, 2, 3, 4, 5, 6, 7, 8] chunk_size = 3 # Using range with step: [data[i:i+chunk_size] for i in range(0, len(data), chunk_size)] # โ [[1, 2, 3], [4, 5, 6], [7, 8]] # Using zip (drops remainder): list(zip(*[iter(data)] * chunk_size))
Remove duplicate values while optionally preserving order.
items = [1, 2, 2, 3, 3, 3, 4] # Preserve order (Python 3.7+): list(dict.fromkeys(items)) # โ [1, 2, 3, 4] # Without order preservation: list(set(items)) # โ [1, 2, 3, 4] (order not guaranteed) # Manual with seen set: seen = set() [x for x in items if not (x in seen or seen.add(x))]
Shift elements left or right by k positions. Efficient slicing technique.
nums = [1, 2, 3, 4, 5] k = 2 # Rotate right by k: nums[-k:] + nums[:-k] # โ [4, 5, 1, 2, 3] # Rotate left by k: nums[k:] + nums[:k] # โ [3, 4, 5, 1, 2] # In-place rotation (O(n) space): nums[:] = nums[-k:] + nums[:-k]
Use a list as a stack. push with append(), pop with pop(). O(1) for both operations.
stack = [] # Push stack.append(1) stack.append(2) stack.append(3) # stack โ [1, 2, 3] # Pop top = stack.pop() # top = 3, stack โ [1, 2] # Peek (view top without removing): top = stack[-1] # 2 # Check if empty: if not stack: print("Empty")
Use a list as a queue. Enqueue with append(), dequeue with pop(0). For frequent ops, use collections.deque.
queue = [] # Enqueue queue.append('Alice') queue.append('Bob') # queue โ ['Alice', 'Bob'] # Dequeue first = queue.pop(0) # first = 'Alice' # queue โ ['Bob'] # โ ๏ธ pop(0) is O(n) โ shifts all elements # For large queues, use collections.deque: from collections import deque d = deque() d.append('Alice') d.popleft() # O(1)
Choosing the right method for adding elements is crucial. Here's when to use each.
| Method | What it does | Result Example | When to use |
|---|---|---|---|
append(x) |
Adds x as a single element at the end | [1,2].append([3,4]) โ [1,2,[3,4]] |
Adding one item; stack push |
extend(iter) |
Adds each element of iter individually | [1,2].extend([3,4]) โ [1,2,3,4] |
Merging lists; adding multiple items |
insert(i, x) |
Inserts x at specific position i | [1,3].insert(1,2) โ [1,2,3] |
Prepending; inserting at specific index |
+ (concat) |
Returns new combined list | [1,2] + [3,4] โ [1,2,3,4] |
When you need a new list, no mutation |
One sorts in-place, the other returns a new list. Know which to use.
| Feature | list.sort() | sorted(list) |
|---|---|---|
| Returns | None (in-place) | New sorted list |
| Original list | Modified | Unchanged |
| Works on | Lists only | Any iterable |
| Memory | O(1) extra | O(n) extra |
| Speed | Slightly faster | Slightly slower |
| Use when | You don't need the original | You need to preserve original |
Common pitfalls and powerful techniques every Python developer should know.
Never use [] as a default argument. It creates one list at function definition time, shared across all calls. Use None instead and assign inside.
Use [x for x in ...] when you need the full list in memory. Use (x for x in ...) for lazy evaluation when iterating once โ saves memory on large datasets.
An empty list is falsy. Use if my_list: instead of if len(my_list) > 0:. It's more Pythonic and slightly faster.
Use *rest to capture remaining elements: first, *middle, last = [1, 2, 3, 4, 5] gives first=1, middle=[2,3,4], last=5.
When checking membership in a loop, convert to a set first: s = set(my_list). Lookup drops from O(n) to O(1).
You can replace entire slices: nums[1:3] = [10, 20, 30] replaces 2 elements with 3. The list length changes automatically.