Lists and Loops
🔁 Lists & Loops
Lists are Python's workhorse collection — flexible, powerful, and everywhere in real code. Python's loop syntax is simpler than Java's but more expressive, especially with list comprehensions, which replace most map() / filter() patterns.
for loop. There is no for (int i = 0; i < n; i++). Python's for is always a for-each. Want an index? Use enumerate(). Want a numeric range? Use range(). List comprehensions replace most stream().map().filter().collect() chains from Java and array.map().filter() from JavaScript — but they're more readable.
📋 Lists — Creation, Indexing & Slicing
Creating Lists
[].list() converts any iterable to a list. range() generates a sequence of integers — combine them to make numeric lists.Indexing & Slicing
Python supports negative indexing and slicing — two features that have no direct Java equivalent and are genuinely useful.
list.get(list.size() - 1) to get the last element!items = ["eggs", "milk", "flour", "butter", "sugar"]
# Positive indexing
print(items[0]) # "eggs" — first
print(items[2]) # "flour"
# Negative indexing — counts from the end
print(items[-1]) # "sugar" — last (no .size()-1 needed!)
print(items[-2]) # "butter" — second to last
stop is exclusive. Any part can be omitted to mean "from the beginning" or "to the end".meals = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
meals[0:3] # → ["Mon", "Tue", "Wed"] (stop is exclusive)
meals[5:] # → ["Sat", "Sun"] (from index 5 to end)
meals[:2] # → ["Mon", "Tue"] (first 2)
meals[-2:] # → ["Sat", "Sun"] (last 2)
meals[::] # → full copy of the list
meals[::-1] # → reversed list (very Pythonic!)
meals[1:6:2] # → ["Tue", "Thu", "Sat"] (every 2nd from 1 to 5)
🛠️ Essential List Methods
Python lists are mutable — methods modify them in place (they return None, not a new list). This is different from string methods, which always return a new value.
pantry = ["flour", "sugar", "salt"]
# Adding
pantry.append("butter") # add to end → ["flour","sugar","salt","butter"]
pantry.insert(1, "eggs") # insert at index 1
pantry.extend(["milk", "cream"]) # add multiple items
# Removing
pantry.remove("salt") # remove by value (first match)
popped = pantry.pop() # remove & return last item
popped = pantry.pop(0) # remove & return item at index 0
pantry.clear() # remove all items
# Reordering
pantry.sort() # sort in place (ascending)
pantry.sort(reverse=True) # sort descending
pantry.reverse() # reverse in place
# Non-mutating alternatives (return new list/value)
new_list = sorted(pantry) # sorted() → new sorted list
n = len(pantry) # length
idx = pantry.index("eggs") # index of first match
count = pantry.count("flour") # how many times it appears
exists = "milk" in pantry # True / False
🔄 Loop Patterns
for(int i=0...) pattern. Never use range(len(x)) when enumerate will do.stop is always exclusive.for when iterating a collection.for/else block is Python-unique — the else runs only if the loop completed without a break.⚡ List Comprehensions
List comprehensions are one of Python's most loved features — a concise way to build a new list by transforming or filtering an existing one. They replace most map() + filter() patterns and are more readable once you're used to them.
# Traditional loop approach
expensive = []
for item in shopping_list:
if item["price"] > 5.0:
expensive.append(item["name"])
# List comprehension — same result, one line
expensive = [item["name"] for item in shopping_list if item["price"] > 5.0]
ingredients = [
{"name": "milk", "days_left": 2, "qty": 1},
{"name": "eggs", "days_left": 10, "qty": 6},
{"name": "yogurt", "days_left": 1, "qty": 2},
{"name": "cheese", "days_left": 5, "qty": 1},
]
# 1. Transform — get just the names
names = [i["name"] for i in ingredients]
# → ["milk", "eggs", "yogurt", "cheese"]
# 2. Filter — items expiring within 3 days
expiring = [i["name"] for i in ingredients if i["days_left"] <= 3]
# → ["milk", "yogurt"]
# 3. Transform with expression
alerts = [
f"{i['name']} expires in {i['days_left']} day(s)!"
for i in ingredients
if i["days_left"] <= 3
]
# → ["milk expires in 2 day(s)!", "yogurt expires in 1 day(s)!"]
# 4. Uppercase all names
upper_names = [i["name"].upper() for i in ingredients]
# → ["MILK", "EGGS", "YOGURT", "CHEESE"]
days = ["Mon", "Tue", "Wed", "Thu", "Fri"]
meals = ["Breakfast", "Lunch", "Dinner"]
# Nested loop — all day/meal combinations
schedule = []
for day in days:
for meal in meals:
schedule.append(f"{day} {meal}")
# Same thing as a comprehension
schedule = [f"{day} {meal}" for day in days for meal in meals]
# Practical nested loop — expiry check across categories
fridge = {
"dairy": ["milk", "yogurt"],
"produce": ["spinach", "carrots"],
}
for category, items in fridge.items():
for item in items:
print(f"[{category}] {item}")
📋 Quick Reference
| Operation | Syntax | Notes |
|---|---|---|
| Create | items = ["a", "b"] | Empty list: items = [] |
| Get by index | items[0] / items[-1] | Negative counts from end |
| Slice | items[1:3] / items[::-1] | stop is exclusive; [::-1] reverses |
| Length | len(items) | Works on all collections and strings |
| Membership | "a" in items | Returns True/False |
| Append | items.append("c") | Adds to end — O(1) |
| Insert | items.insert(1, "x") | Inserts at index — O(n) |
| Extend | items.extend(other) | Add all items from another list |
| Remove by value | items.remove("a") | Removes first match — raises ValueError if missing |
| Remove by index | items.pop(0) | Returns the removed item |
| Sort in place | items.sort() | Returns None — modifies original |
| Sort (new list) | sorted(items) | Returns new sorted list — original unchanged |
| Reverse | items.reverse() | In place — or use items[::-1] for new list |
| for-each | for x in items: | Always prefer over index-based loops |
| With index | for i, x in enumerate(items): | Replaces for(int i=0...) |
| Parallel | for a, b in zip(l1, l2): | Stops at shortest list |
| Range | for i in range(5): | range(start, stop, step) |
| Comprehension | [f(x) for x in items if cond] | Transform + filter in one expression |
| Copy | items.copy() / items[:] | Shallow copy — see gotcha below! |
Assignment copies the reference, not the list —
b = a makes both variables point to the same list. Changing b changes a too. To copy, use b = a.copy() or b = a[:]. This is the same as Java object references — it just surprises people who expect value semantics.sort() returns None — unlike Java's
Collections.sort() which also returns void, Python beginners often write items = items.sort() and wonder why items is now None. Use items.sort() to sort in place, or items = sorted(items) to get a new sorted list.Never modify a list while iterating over it — removing items from a list inside a
for loop over that same list causes skipped items and hard-to-find bugs. Instead, iterate over a copy: for item in items.copy(): or build a new list with a comprehension.range() is lazy —
range(1000000) doesn't create a million-element list in memory. It generates numbers on demand. This is a good thing — just don't be surprised when print(range(5)) shows range(0, 5) instead of a list.